iOS的XMPPFramework简单介绍(实现及时通信)
xmppframework是一个os x/ios平台的开源项目,使用objective-c实现了xmpp协议(rfc-3920),同时还提供了用于读写xml的工具,大大简化了基于xmpp的通信应用的开发。
1. 登录和好友上下线
1.1xmpp中常用对象们
- xmppstream:xmpp基础服务类
- xmpproster:好友列表类
- xmpprostercoredatastorage:好友列表(用户账号)在core data中的操作类
- xmppvcardcoredatastorage:好友名片(昵称,签名,性别,年龄等信息)在core data中的操作类
- xmppvcardtemp:好友名片实体类,从数据库里取出来的都是它
- xmppvcardavatarmodule:好友头像
- xmppreconnect:如果失去连接,自动重连
- xmpproom:提供多用户聊天支持
- xmpppubsub:发布订阅
1.2登录操作,也就是连接xmpp服务器
- (void)connect { if (self.xmppstream == nil) { self.xmppstream = [[xmppstream alloc] init]; [self.xmppstream adddelegate:self delegatequeue:dispatch_get_main_queue()]; } if (![self.xmppstream isconnected]) { nsstring *username = [[nsuserdefaults standarduserdefaults] objectforkey:@"username"]; xmppjid *jid = [xmppjid jidwithuser:username domain:@"lizhen" resource:@"ework"]; [self.xmppstream setmyjid:jid]; [self.xmppstream sethostname:@"10.4.125.113"]; nserror *error = nil; if (![self.xmppstream connect:&error]) { nslog(@"connect error: %@", [[error userinfo] description]); } } }
connect成功之后会依次调用xmppstreamdelegate的方法,首先调用
- (void)xmppstream:(xmppstream *)sender socketdidconnect:(gcdasyncsocket *)socket
然后
- (void)xmppstreamdidconnect:(xmppstream *)sender
在该方法下面需要使用xmppstream 的authenticatewithpassword方法进行密码验证,成功的话会响应delegate的方法,就是下面这个
- (void)xmppstreamdidauthenticate:(xmppstream *)sender
1.3上线
实现 - (void)xmppstreamdidauthenticate:(xmppstream *)sender 委托方法
- (void)xmppstreamdidauthenticate:(xmppstream *)sender { xmpppresence *presence = [xmpppresence presencewithtype:@"available"]; [self.xmppstream sendelement:presence]; }
1.4退出并断开连接
- (void)disconnect { xmpppresence *presence = [xmpppresence presencewithtype:@"unavailable"]; [self.xmppstream sendelement:presence]; [self.xmppstream disconnect]; }
1.5好友状态
获取好友状态,通过实现
- (void)xmppstream:(xmppstream *)sender didreceivepresence:(xmpppresence *)presence ...
方法,当接收到 presence 标签的内容时,xmppframework 框架回调该方法
一个 presence 标签的格式一般如下:
presence 的状态:
- available 上线
- away 离开
- do not disturb 忙碌
- unavailable 下线
- (void)xmppstream:(xmppstream *)sender didreceivepresence:(xmpppresence *)presence { nsstring *presencetype = [presence type]; nsstring *presencefromuser = [[presence from] user]; if (![presencefromuser isequaltostring:[[sender myjid] user]]) { if ([presencetype isequaltostring:@"available"]) { // } else if ([presencetype isequaltostring:@"unavailable"]) { // } } }
2. 接收消息和发送消息
2.1接收消息
当接收到 message 标签的内容时,xmppframework 框架回调该方法
根据 xmpp 协议,消息体的内容存储在标签 body 内
- (void)xmppstream:(xmppstream *)sender didreceivemessage:(xmppmessage *)message { nsstring *messagebody = [[message elementforname:@"body"] stringvalue]; }
2.2发送消息
发送消息,我们需要根据 xmpp 协议,将数据放到标签内,例如:
- (void)sendmessage:(nsstring *) message touser:(nsstring *) user { nsxmlelement *body = [nsxmlelement elementwithname:@"body"]; [body setstringvalue:message]; nsxmlelement *message = [nsxmlelement elementwithname:@"message"]; [message addattributewithname:@"type" stringvalue:@"chat"]; nsstring *to = [nsstring stringwithformat:@"%@@example.com", user]; [message addattributewithname:@"to" stringvalue:to]; [message addchild:body]; [self.xmppstream sendelement:message]; }
3. 获取好友信息和删除好友
3.1好友列表和好友名片
[_xmpproster fetchroster];//获取好友列表 //获取到一个好友节点 - (void)xmpproster:(xmpproster *)sender didrecieverosteritem:(nsxmlelement *)item //获取完好友列表 - (void)xmpprosterdidendpopulating:(xmpproster *)sender //到服务器上请求联系人名片信息 - (void)fetchvcardtempforjid:(xmppjid *)jid; //请求联系人的名片,如果数据库有就不请求,没有就发送名片请求 - (void)fetchvcardtempforjid:(xmppjid *)jid ignorestorage:(bool)ignorestorage; //获取联系人的名片,如果数据库有就返回,没有返回空,并到服务器上抓取 - (xmppvcardtemp *)vcardtempforjid:(xmppjid *)jid shouldfetch:(bool)shouldfetch; //更新自己的名片信息 - (void)updatemyvcardtemp:(xmppvcardtemp *)vcardtemp; //获取到一盒联系人的名片信息的回调 - (void)xmppvcardtempmodule:(xmppvcardtempmodule *)vcardtempmodule didreceivevcardtemp:(xmppvcardtemp *)vcardtemp forjid:(xmppjid *)jid
3.2添加好友
//name为用户账号 - (void)xmppaddfriendsubscribe:(nsstring *)name { //xmpphost 就是服务器名, 主机名 xmppjid *jid = [xmppjid jidwithstring:[nsstring stringwithformat:@"%@@%@",name,xmpphost]]; //[presence addattributewithname:@"subscription" stringvalue:@"好友"]; [xmpproster subscribepresencetouser:jid]; }
3.3收到添加好友的请求
- (void)xmpproster:(xmpproster *)sender didreceivepresencesubscriptionrequest:(xmpppresence *)presence { //取得好友状态 nsstring *presencetype = [nsstring stringwithformat:@"%@", [presence type]]; //online/offline //请求的用户 nsstring *presencefromuser =[nsstring stringwithformat:@"%@", [[presence from] user]]; nslog(@"presencetype:%@",presencetype); nslog(@"presence2:%@ sender2:%@",presence,sender); xmppjid *jid = [xmppjid jidwithstring:presencefromuser]; //接收添加好友请求 [xmpproster acceptpresencesubscriptionrequestfrom:jid andaddtoroster:yes]; }
3.4删除好友
//删除好友,name为好友账号 - (void)removebuddy:(nsstring *)name { xmppjid *jid = [xmppjid jidwithstring:[nsstring stringwithformat:@"%@@%@",name,xmpphost]]; [self xmpproster] removeuser:jid]; }
4. 聊天室
初始化聊天室
xmppjid *roomjid = [xmppjid jidwithstring:room_jid]; xmpproom = [[xmpproom alloc] initwithroomstorage:self jid:roomjid]; [xmpproom activate:xmppstream]; [xmpproom adddelegate:self delegatequeue:dispatch_get_main_queue()];
创建聊天室成功
- (void)xmpproomdidcreate:(xmpproom *)sender { ddloginfo(@"%@: %@", this_file, this_method); }
加入聊天室,使用昵称
[xmpproom joinroomusingnickname:@"quack" history:nil];
获取聊天室信息
- (void)xmpproomdidjoin:(xmpproom *)sender { [xmpproom fetchconfigurationform]; [xmpproom fetchbanlist]; [xmpproom fetchmemberslist]; [xmpproom fetchmoderatorslist]; }
如果房间存在,会调用委托
// 收到禁止名单列表 - (void)xmpproom:(xmpproom *)sender didfetchbanlist:(nsarray *)items; // 收到好友名单列表 - (void)xmpproom:(xmpproom *)sender didfetchmemberslist:(nsarray *)items; // 收到主持人名单列表 - (void)xmpproom:(xmpproom *)sender didfetchmoderatorslist:(nsarray *)items;
房间不存在,调用委托
- (void)xmpproom:(xmpproom *)sender didnotfetchbanlist:(xmppiq *)iqerror; - (void)xmpproom:(xmpproom *)sender didnotfetchmemberslist:(xmppiq *)iqerror; - (void)xmpproom:(xmpproom *)sender didnotfetchmoderatorslist:(xmppiq *)iqerror;
离开房间
[xmpproom deactivate:xmppstream];
xmpproomdelegate的其他代理方法:
离开聊天室
- (void)xmpproomdidleave:(xmpproom *)sender { ddlogverbose(@"%@: %@", this_file, this_method); }
新人加入群聊
- (void)xmpproom:(xmpproom *)sender occupantdidjoin:(xmppjid *)occupantjid { ddlogverbose(@"%@: %@", this_file, this_method); }
有人退出群聊
- (void)xmpproom:(xmpproom *)sender occupantdidleave:(xmppjid *)occupantjid { ddlogverbose(@"%@: %@", this_file, this_method); }
有人在群里发言
- (void)xmpproom:(xmpproom *)sender didreceivemessage:(xmppmessage *)message fromoccupant:(xmppjid *)occupantjid { ddlogverbose(@"%@: %@", this_file, this_method); }
5. 消息回执
这个是xep-0184协议的内容。协议内容:
发送消息时附加回执请求
代码实现
nsstring *siid = [xmppstream generateuuid]; //发送消息 xmppmessage *message = [xmppmessage messagewithtype:@"chat" to:jid elementid:siid]; nsxmlelement *receipt = [nsxmlelement elementwithname:@"request" xmlns:@"urn:xmpp:receipts"]; [message addchild:receipt]; [message addbody:@"测试"]; [self.xmppstream sendelement:message];
收到回执请求的消息,发送回执
代码实现
- (void)xmppstream:(xmppstream *)sender didreceivemessage:(xmppmessage *)message { //回执判断 nsxmlelement *request = [message elementforname:@"request"]; if (request) { if ([request.xmlns isequaltostring:@"urn:xmpp:receipts"])//消息回执 { //组装消息回执 xmppmessage *msg = [xmppmessage messagewithtype:[message attributestringvalueforname:@"type"] to:message.from elementid:[message attributestringvalueforname:@"id"]]; nsxmlelement *recieved = [nsxmlelement elementwithname:@"received" xmlns:@"urn:xmpp:receipts"]; [msg addchild:recieved]; //发送回执 [self.xmppstream sendelement:msg]; } }else { nsxmlelement *received = [message elementforname:@"received"]; if (received) { if ([received.xmlns isequaltostring:@"urn:xmpp:receipts"])//消息回执 { //发送成功 nslog(@"message send success!"); } } } //消息处理 //... }
6. 添加autoping
为了监听服务器是否有效,增加心跳监听。用xep-0199协议,在xmppframework框架下,封装了 xmppautoping 和 xmppping两个类都可以使用,因为xmppautoping已经组合进了xmppping类,所以xmppautoping使用起来更方便。
//初始化并启动ping -(void)autopingproxyserver:(nsstring*)strproxyserver { _xmppautoping = [[xmppautopingalloc] init]; [_xmppautopingactivate:_xmppstream]; [_xmppautopingadddelegate:selfdelegatequeue: dispatch_get_main_queue()]; _xmppautoping.respondstoqueries = yes; _xmppautoping.pinginterval=2;//ping 间隔时间 if (nil != strproxyserver) { _xmppautoping.targetjid = [xmppjid jidwithstring: strproxyserver ];//设置ping目标服务器,如果为nil,则监听socketstream当前连接上的那个服务器 } } //卸载监听 [_xmppautoping deactivate]; [_xmppautoping removedelegate:self]; _xmppautoping = nil; //ping xmppautopingdelegate的委托方法: - (void)xmppautopingdidsendping:(xmppautoping *)sender { nslog(@"- (void)xmppautopingdidsendping:(xmppautoping *)sender"); } - (void)xmppautopingdidreceivepong:(xmppautoping *)sender { nslog(@"- (void)xmppautopingdidreceivepong:(xmppautoping *)sender"); } - (void)xmppautopingdidtimeout:(xmppautoping *)sender { nslog(@"- (void)xmppautopingdidtimeout:(xmppautoping *)sender"); }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。