我们在第一篇文章中,已经介绍了Openfire服务器的搭建等环境的配置,
第二篇文章中,导入了XMPPFramework框架,
这一篇,我们将正式进入代码环节,说一说用户的登陆。
1、我们选择新建一个XMPPManager来统一管理即时聊天模块,当然,这个对象得要是个单例。并在其中配置控制台打印设置,这样能让我们看得更清楚些。
+ (instancetype)sharedInstance { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ instance = [[XMPPManager alloc] init]; //配置日志打印工具 [DDLog addLogger:[DDTTYLogger sharedInstance] withLogLevel:XMPP_LOG_FLAG_SEND_RECV]; //打开控制台文字色彩 [[DDTTYLogger sharedInstance] setColorsEnabled:YES]; //XMPP_LOG_FLAG_SEND | XMPP_LOG_FLAG_RECV_POST 给这2个级别一人一个颜色 [[DDTTYLogger sharedInstance] setForegroundColor:[UIColor orangeColor] backgroundColor:[UIColor whiteColor] forFlag:XMPP_LOG_FLAG_SEND]; [[DDTTYLogger sharedInstance] setForegroundColor:[UIColor magentaColor] backgroundColor:[UIColor whiteColor] forFlag:XMPP_LOG_FLAG_RECV_POST]; }); return instance; }
我们首先在这个单例中初始化一个XMPPStream对象,起到连接的作用。我们用getter方法进行加载:
- (XMPPStream *)xmppStream { if (_xmppStream == nil) { _xmppStream = [[XMPPStream alloc] init]; [_xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()]; [_xmppStream setHostName:@"172.10.0.95"]; [_xmppStream setHostPort:5222]; [self setupModule]; } return _xmppStream; }
我们先对XMPPStream进行初始化,再用addDelegate: delegateQueue:方法添加XMPPManager对象为代理。
这里的第二个参数需要注意,需要传入一个队列,这个队列,决定了回调执行的队列,是在主队列还是其他队列。
另外,XMPPStream对象可以添加多个代理,实现的原理我们会在以后讨论。简单来说,内部的实现,就是将其加入一个数组中。
HostName和HostPort是本机配置的Openfire服务器的地址和端口,并且在最后设置我们需要用到的模块。
2、设置模块
// 设置模块 - (void)setupModule { // 心跳检测 self.xmppAutoPing = [[XMPPAutoPing alloc] initWithDispatchQueue:dispatch_get_main_queue()]; // 客户端检测频率 [self.xmppAutoPing setPingTimeout:360.0f]; // 是否响应对方的ping [self.xmppAutoPing setRespondsToQueries:YES]; [self.xmppAutoPing addDelegate:self delegateQueue:dispatch_get_main_queue()]; // 自动重连模块 self.xmppReconnect = [[XMPPReconnect alloc] initWithDispatchQueue:dispatch_get_main_queue()]; [self.xmppReconnect setAutoReconnect:YES]; // 激活 [self.xmppAutoPing activate:self.xmppStream]; [self.xmppReconnect activate:self.xmppStream]; }
我们可以根据注释看到,分别设置了心跳检测模块,自动重连模块,并且设置了代理,并分别在XMPPStream对象上进行激活,不然不会工作。
3、连接及身份验证
我们写了一个连接登录的方法
- (void)loginWithJid:(XMPPJID *)aJid addPassword:(NSString *)password { self.myJID = aJid; [self.xmppStream setMyJID:aJid]; [self.xmppStream connectWithTimeout:XMPPStreamTimeoutNone error:nil]; self.myPassword = password; }
这里需要说明,JID代表了每个用户,一般由三部分构成:用户名,域名和资源名,例如 [email protected]/Anthony。
我们保存下来当前准备连接登录用户的JID和密码,并调用connectWithTimeout:error:进行连接。
还记得我们之前给XMPPStream对象设置的代理吗?现在就派上用场啦,我们刚刚设置的,在主队列进行回调,下面是回调方法。
/** * socket连接建立成功 三次握手成功 */ - (void)xmppStream:(XMPPStream *)sender socketDidConnect:(GCDAsyncSocket *)socket { // [self.xmppStream authenticateWithPassword:self.myPassword error:nil]; } /** * XML 流被完全打开的时候调用 * At this point it's safe to begin communication with the server. * 在这个时间点 跟服务器对话是安全的 **/ - (void)xmppStreamDidConnect:(XMPPStream *)sender { //1.登录 //2.上线 [self.xmppStream authenticateWithPassword:self.myPassword error:nil]; } //登录成功的委托 - (void)xmppStreamDidAuthenticate:(XMPPStream *)sender { //<presence from= to= type= > //<show--系统状态图标/><status/> //</presence> //<presence/> //1.上线 XMPPPresence *presence = [XMPPPresence presence]; [presence addChild:[DDXMLElement elementWithName:@"show" stringValue:@"xa"]]; [presence addChild:[DDXMLElement elementWithName:@"status" stringValue:@"快来找我聊天吧"]]; [self.xmppStream sendElement:presence]; }
连接成功的情况下,会调用第一个和第二个方法。我们在第二个方法里面写登录认证,认证成功后,调用第三个方法,这样,我们就登录成功了!
第三个方法中,我们可以设置我们的上线状态,调用sendElement:方法传一个XMPPPresence对象,告诉服务器我的登录状态。
当然,也有连接失败的情况,会进入下面的回调:
- (void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error { } - (void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(DDXMLElement *)error { }
当出现失败的情况,可以找一下是不是网络的原因,或者对照下上面说的模块,如果没有解决,欢迎贴出来大家讨论一下~
以上就是用户登录的内容,下一篇,我们来说一说好友模块,下篇见~