1. 即时通信

 1> 概述

  即时通讯(Instant Messaging)是目前Internet上最为流行的通讯方式,各种各样的即时通讯软件也层出不穷,服务提供商也提供了越来越丰富的通讯服务功能。

  即时通讯有多种实现方式,例如:XMPP、环信、融云等。

 2> XMPP(可扩展消息处理现场协议)

  XMPP(XML Messages Presence Protocol(可扩展消息处理现场协议))是基于可扩展标记语言(XML)的协议,可用于即时通信(IM)。

 3> XMPP的优点

  • 开放

  XMPP协议是由JSF开源社区组织开发的,不属于任何的机构和个人,从根本上保证了其开放性。

  • 标准

  互联网工程工作组将XMPP于2002年正式列为认可的实时通讯及Presence技术。

  • 分布式的网络架构

  XMPP 协议虽然是基于Client/Server 架构,但是XMPP协议本身并没有这样的限制。网络的架构和电子邮件十分相似,但没有结合任何特定的网络架构,适用范围非常广泛。

  • XMPP 协议具有良好的扩展性

  基于XML 建立起来的应用具有良好的语义完整性和扩展性。

  • XMPP 具有很好的弹性

  XMPP 除了可用在即时通信的应用程序,还能用在网络管理、内容供稿、协同工具、档案共享、游戏、远端系统监控等。

  • 安全性

  XMPP在Client-to-Server通信和Server-to-Server通信中都使用TLS (Transport Layer Security)协议作为通信通道的加密方法,保证通信的安全。

  XMPP环境的搭建的步骤详见XMPP环境的搭建

2. 工程中添加XMPP

  将XMPP协议第三方文件拖入工程,下载地址:https://github.com/AlonerOwl/XMPPFramework

3. 登录、注册

 1> 界面搭建

  界面采用Storyboard,效果图如下:

 2> 初始化XMPP通道

        //初始化通道
self.xmppStream = [[XMPPStream alloc] init];
//openfire服务器IP地址
self.xmppStream.hostName = kHostName;
//openfire服务器端口 默认5222
self.xmppStream.hostPort = kHostPort;
//添加代理
[self.xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()
];

 3> 连接服务器代码所需方法

 4> 登录代码所需方法

 5> 注册代码所需方法

 

 6> 全部代码(方法的使用详见代码注释)

  • 封装的XMPP控制器代码:

   XMPPManager.h

#import <Foundation/Foundation.h>

#import "XMPPFramework.h"

@interface XMPPManager : NSObject

/// 声明XMPP通道属性
@property (nonatomic, strong) XMPPStream *xmppStream; + (XMPPManager *)shareXMPPManager; // 登录方法
- (void)loginWithUsername:(NSString *)username
password:(NSString *)password;
// 注册方法
- (void)registerWithUsername:(NSString *)username
password:(NSString *)password; @end

  XMPPManager.m

#import "XMPPManager.h"

static XMPPManager *xmppManager = nil;

// 枚举记录状态
typedef NS_ENUM(NSUInteger, ConnectToServerPurpose) {
ConnectToServerPurposeLogin,
ConnectToServerPurposeRegister
}; // 遵循协议
@interface XMPPManager () <XMPPStreamDelegate> /// 用户名
@property (nonatomic, copy) NSString *username; /// 密码
@property (nonatomic, copy) NSString *password; /// 记录当前的状态,判断是登录还是注册
@property (nonatomic) ConnectToServerPurpose connectToServer; @end @implementation XMPPManager + (XMPPManager *)shareXMPPManager
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
xmppManager = [XMPPManager new];
});
return xmppManager;
} #pragma mark - 1.创建通道
- (instancetype)init
{
self = [super init];
if (self) {
//初始化对象
self.xmppStream = [XMPPStream new]; // 设置服务器
[self settingUpServer];
}
return self;
} // 设置服务器
- (void)settingUpServer
{
// 设置opfire服务器
self.xmppStream.hostName = kHostName;
// 设置服务器端口号
self.xmppStream.hostPort = kHostPort;
// 添加代理
[self.xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
} #pragma mark - 登录的方法
- (void)loginWithUsername:(NSString *)username
password:(NSString *)password
{
self.username = username;
self.password = password; // 记录登录状态
self.connectToServer = ConnectToServerPurposeLogin; // 连接服务器
[self linkServer];
} #pragma mark - 注册的方法
- (void)registerWithUsername:(NSString *)username
password:(NSString *)password
{
self.username = username;
self.password = password; // 记录注册状态
self.connectToServer = ConnectToServerPurposeRegister; // 连接服务器
[self linkServer];
} #pragma mark - 连接服务器
- (void)linkServer
{
// 要连接服务器,要有用户身份认证
// 身份证
// 参数1:用户名
// 参数2:域名
// 参数3:资源
XMPPJID *jid = [XMPPJID jidWithUser:self.username domain:kDomin resource:kResource]; self.xmppStream.myJID = jid; // 如果当前聊天工具处于连接状态或已经连接,此时,你需要去切断连接【此逻辑不唯一】
if ([self.xmppStream isConnected] || [self.xmppStream isConnecting]) {
// 断开连接
[self disConnectToServer];
} // 设置连接超时
NSError *error = nil;
[self.xmppStream connectWithTimeout:30 error:&error];
if (error) {
NSLog(@"连接超时");
} } #pragma mark - 断开连接(自己写的)
- (void)disConnectToServer
{
// 当前用户不可用(下线了)
XMPPPresence *presence = [XMPPPresence presenceWithType:@"unavailable"];
// 告诉通道用户不可用(下线了)
[self.xmppStream sendElement:presence];
// 使用通道失去连接
[self.xmppStream disconnect];
} #pragma mark - XMPPStreamDelegate协议方法 #pragma mark 连接超时
- (void)xmppStreamConnectDidTimeout:(XMPPStream *)sender
{
NSLog(@"连接超时");
} #pragma mark 连接成功
- (void)xmppStreamDidConnect:(XMPPStream *)sender
{
NSLog(@"连接成功"); // 认证密码
// [self.xmppStream authenticateWithPassword:self.password error:nil]; // 区分登录和注册进行密码验证
switch (self.connectToServer) {
case ConnectToServerPurposeLogin:
// 登录认证
[self.xmppStream authenticateWithPassword:self.password error:nil];
break; case ConnectToServerPurposeRegister:
// 注册的认证
[self.xmppStream registerWithPassword:self.password error:nil];
break; default:
break;
}
} #pragma mark 断开连接
- (void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error
{
// 1. 自己动手断开
// 2. 被动断开
if (error) {
NSLog(@"断开连接,error == %@", error);
}
} #pragma mark 认证失败
- (void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(DDXMLElement *)error
{
NSLog(@"认证失败:error = %@", error);
} #pragma mark 认证成功
- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender
{
// 当前用户可用(上线了)
XMPPPresence *presence = [XMPPPresence presenceWithType:@"available"];
// 告诉通道用户可用(上线了)
[self.xmppStream sendElement:presence]; NSLog(@"认证成功");
} @end
  • 登录界面

  LoginViewController.m

#import "LoginViewController.h"

#import "XMPPManager.h"

@interface LoginViewController ()

/// 用户输入框
@property (weak, nonatomic) IBOutlet UITextField *usernameTextField; /// 密码输入框
@property (weak, nonatomic) IBOutlet UITextField *passwordTextField; @end @implementation LoginViewController - (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
} - (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
} - (IBAction)loginAction:(UIButton *)sender
{
[[XMPPManager shareXMPPManager] loginWithUsername:self.usernameTextField.text password:self.passwordTextField.text];
} @end
  • 注册界面

   RegisterViewController.m

#import "RegisterViewController.h"

#import "XMPPManager.h"

@interface RegisterViewController () <XMPPStreamDelegate>

@property (weak, nonatomic) IBOutlet UITextField *registerUNTextField;
@property (weak, nonatomic) IBOutlet UITextField *registerPWTextField; @end @implementation RegisterViewController - (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view. // 添加代理
[[XMPPManager shareXMPPManager].xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
} - (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
} // 按钮点击事件
- (IBAction)registerAction:(id)sender
{
[[XMPPManager shareXMPPManager] registerWithUsername:self.registerUNTextField.text password:self.registerPWTextField.text];
} #pragma mark - XMPPStreamDelegate实现协议方法
// 注册成功后,dismiss到登录界面
- (void)xmppStreamDidRegister:(XMPPStream *)sender
{
NSLog(@"注册成功");
[self dismissViewControllerAnimated:YES completion:nil];
} // 注册失败
- (void)xmppStream:(XMPPStream *)sender didNotRegister:(DDXMLElement *)error
{
NSLog(@"注册失败:%@", error);
} @end

iOS开发-即时通信XMPP的更多相关文章

  1. iOS开发拓展篇-XMPP简单介绍

    iOS开发拓展篇-XMPP简单介绍 一.即时通讯简单介绍 1.简单说明 即时通讯技术(IM)支持用户在线实时交谈.如果要发送一条信息,用户需要打开一个小窗口,以便让用户及其朋友在其中输入信息并让交谈双 ...

  2. android-使用环信SDK开发即时通信功能及源代码下载

    近期项目中集成即时聊天功能.挑来拣去,终于选择环信SDK来进行开发,选择环信的主要原因是接口方便.简洁.说明文档清楚易懂.文档有android.ios.和后台server端.还是非常全的. 环信官网: ...

  3. iOS开发--即时通讯

    什么是环信? 1.环信是一个第三平台,提供即时通信(IM–Instant Messaging )的服务 2.环信是在XMPP的基础上进行二次开发 3.环信在网络上传输的数据也是XML 4.使用环信,不 ...

  4. iOS开发--即时通讯常用第三方库

    前言 自毕业到现在,从事iOS即时通讯开发已经1年半之久.主要负责Allure开发,目前已上架,可以在苹果商店搜素Allure.Allure模仿微信的交互和设计效果,已经实现微信的大部分功能. 在这里 ...

  5. iOS开发--线程通信

    线程间的通信主要用于主线程与子线程的,也有用于子线程与子线程的 介绍下面几种通信方式 1.利用GCD方式(推荐) - (void)touchesBegan:(NSSet<UITouch *> ...

  6. ios开发 Socket通信

    Socket描述了一个IP.端口对.它简化了程序员的操作,知道对方的IP以及PORT就可以给对方发送消息,再由服务器端来处理发送的这些消息.所以,Socket一定包含了通信的双发,即客户端(Clien ...

  7. iOS开发之使用XMPPFramework实现即时通信

    iOS开发之使用XMPPFramework实现即时通信   关于XMPP的理论介绍在本篇博客中就不做赘述了,如何在我们之前的微信中加入XMPP协议来实现通信呢?下面将会介绍一下XMPP的基本的知识,让 ...

  8. iOS开发之使用XMPPFramework实现即时通信(三)

    你看今天是(三)对吧,前面肯定有(一)和(二),在发表完iOS开发之使用XMPPFramework实现即时通信(一)和iOS开发之使用XMPPFramework实现即时通信(二)后有好多的小伙伴加我Q ...

  9. iOS开发之使用XMPPFramework实现即时通信(二)

    上篇的博客iOS开发之使用XMPPFramework实现即时通信(一)只是本篇的引子,本篇博客就给之前的微信加上即时通讯的功能,主要是对XMPPFramework的使用.本篇博客中用到了Spark做测 ...

随机推荐

  1. ASP.NET CSS 小结

    1.ASP.NET 引用CSS 1.Site.master里面设置webopt <webopt:bundlereferencerunat="server"path=" ...

  2. 试着讲清楚:js代码运行机制

    一. js运行机制 js执行引擎 经常看文章的说到js是带线程的,其实这个说法非常的模糊,准确的是js执行引擎是单线程的,js执行引擎就是js代码的执行器,有了这个概念就可以下来说说js是如何运行的了 ...

  3. mini-css-extract-plugin 的用法(webpack4)

    今天在使用webpack的extract-text-webpack-plugin插件提取单独打包css文件时,报错,说是这个插件要依赖webpack3的版本. 后面查了一下,webpack4得使用mi ...

  4. 【BZOJ4652】【NOI2016】循环之美(莫比乌斯反演,杜教筛)

    [BZOJ4652]循环之美(莫比乌斯反演,杜教筛) 题解 到底在求什么呢... 首先不管他\(K\)进制的问题啦,真是烦死啦 所以,相当于有一个分数\(\frac{i}{j}\) 因为值要不相等 所 ...

  5. [CodeVS2370] 小机房的树 (LCA, 树链剖分, LCT)

    Description 小机房有棵焕狗种的树,树上有N个节点,节点标号为0到N-1,有两只虫子名叫飘狗和大吉狗,分居在两个不同的节点上.有一天,他们想爬到一个节点上去搞基,但是作为两只虫子,他们不想花 ...

  6. CANopen--基于DS402协议的伺服电机原点回零模式实现

    硬件:Copley 驱动器ACJ-055-18+Maxon DCX-35L电机 1.原点回零方式简介: 有几种原点回零方法,每种方法建立:原点参考(限位或原点开关转换或编码器索引脉冲)运动方向以及索引 ...

  7. hadoop第二课

    1.1为什么需要Hadoop  (1)数据分析者面临的问题 – 数据日趋庞大,读写都出现性能瓶颈: – 用户的应用和分析结果,对实时性和响应时间 要求越来越高: – 使用的模型越来越复杂,计算量指数级 ...

  8. 【learning】莫比乌斯反演

    吐槽 额其实这个东西的话..好像缠着机房里面的dalao们给我讲过好多遍了然后.. 拖到现在才搞懂也是服了qwq(可能有个猪脑子) 感觉就是主要几条式子然后疯狂换元换着换着就化简运算了? 草稿纸杀手q ...

  9. Bounding-box 回归

    R-CNN系列均训练了Bounding-box回归器来对窗口进行校正,其目标是学习一种转换关系将预测得到的窗口P映射为真实窗口G(Ground truth). 变换方式 可以通过简单的仿射变换以及指数 ...

  10. Spring AOP梳理

    一.Srping AOP AOP(Aspect Oriented Programming)解释为面向切面编程,何为切面,用刀把一块面包切成两半,刀切下去形成的面就叫切面,那么面向切面的就是形成切面的这 ...