首页 > 学院 > 开发设计 > 正文

iOS中XMPP即时通讯实现的主要步骤

2019-11-14 17:53:20
字体:
来源:转载
供稿:网友

这里只是列出实现的只要步骤,不是全部代码。

首先导入XMPPFramework,及相关配置,完成后开始。

创建一个XMPPHelper  类来管理要进行的操作。

XMPPHelper.h文件如下

 1 typedef void(^loginSuccessBlock)(void); 2 typedef void(^loginFailBlock)(NSString *info); 3 typedef void(^fenchFridendList)(id result); 4 typedef void(^logoutSuccessBlock)(void); 5 typedef void(^registerSuccessBlock)(void); 6 typedef enum { 7     kTypeLogin, 8     kTypeRegister 9 }ConnectType;10 #import <Foundation/Foundation.h>11 #define kXMPPHosetName @"lala"12 #define kXMPPHostAddress @"192.168.13.17"13 #define kHostPort 522214 15 @interface XMPPHelper : NSObject16 {17 18     ConnectType _connectType;19 20 }21 @PRoperty(nonatomic,strong)XMPPStream *stream;22 @property(nonatomic,strong)XMPPRoster *roster;23 @property(nonatomic,copy)NSString *username;24 @property(nonatomic,copy)NSString *passWord;25 26 @property(nonatomic,copy)loginSuccessBlock loginSuccessBlock;27 @property(nonatomic,copy)loginFailBlock loginFailBlock;28 @property(nonatomic,copy)fenchFridendList fenchFriendList;29 @property(nonatomic,copy)logoutSuccessBlock logoutSuccessBlock;30 @property(nonatomic,copy)registerSuccessBlock registerSuccessblock;31 32 +(instancetype)shareInstance;33 //登陆34 -(void)login:(NSString *)username password:(NSString *)password loginSuccessBlock:(loginSuccessBlock)block loginFailBlock:(loginFailBlock)failBlcok;35 //获取好友列表36 -(void)loadFriendList:(fenchFridendList)fenchfriendList;37 //发送消息38 -(void)sendMessage:(NSString *)message toUser:(NSString *)jid;39 //注销40 -(void)logoutAction:(logoutSuccessBlock)block;41 //注册42 -(void)registerAction:(NSString *)username password:(NSString *)password registerSuccessBlock:(registerSuccessBlock)registerBlock;43 44 @end

XMPPHelper.m文件如下

#define kHostAddress @"192.168.13.12"#define kHostName @"zy"#define KHostPort 5222#import "XMPPHelper.h"#import "User.h"static XMPPHelper *helper = nil;@interface XMPPHelper() <XMPPStreamDelegate>{    ConnectTyep _connectType;}@end@implementation XMPPHelper//单例+ (instancetype) shareInstance {    static dispatch_once_t onceToken;    dispatch_once(&onceToken, ^{        helper = [[XMPPHelper alloc] init];        [helper _stepXMPPHelper];    });    return helper;}//初始化的操作- (void) _stepXMPPHelper {    //初始化流对象.    self.stream = [[XMPPStream alloc] init];    //创建自动连接的对象,当意外断开的时候,可以进行自动连接.    XMPPReconnect *reConnect = [[XMPPReconnect alloc] init];        //初始化花名册对象(好友列表)    //存储方式.    XMPPRosterCoreDataStorage *storage = [[XMPPRosterCoreDataStorage alloc] init];    self.roster = [[XMPPRoster alloc] initWithRosterStorage:storage];        //建立对象之间的联系    //激活.    [reConnect activate:self.stream];    //激活,使用花名册对象.    [self.roster activate:self.stream];        //设置代理;    [self.stream addDelegate:self delegateQueue:dispatch_get_main_queue()];    [self.roster addDelegate:self delegateQueue:dispatch_get_main_queue()];        //设置服务器的基本信息.    //服务器的地址    [self.stream setHostName:kHostAddress];    [self.stream setHostPort:KHostPort];    //端口号}#pragma mark XMPP 对外公开方法- (void) login:(NSString *)userName password:(NSString *)password loginSuccessBlock:(LoginSuccessBlock)block loginFailBlock:(LoginFailBlock)failBlock {        _connectType = kTypeLogin;        self.userName = userName;    self.password = password;    self.loginFailBlock = failBlock;    self.loginSuccessBlock = block;    //登录的流程.    if (![self connect]) {        //连接失败的时候 调用失败的block        if (self.loginFailBlock) {            self.loginFailBlock(@"网络错误");        }    }}//发起连接- (BOOL) connect {    //设置用户的jid    NSString *jidString = [NSString stringWithFormat:@"%@@%@",self.userName,kHostName];    //创建了一个jid对象    XMPPJID *jid = [XMPPJID jidWithString:jidString];    [self.stream setMyJID:jid];    NSError *ERROR = nil;  return [self.stream connectWithTimeout:10 error:&ERROR];}//上线的方法- (void) online {    //默认情况下 上线的状态    XMPPPresence *presence = [XMPPPresence presence];    [self.stream sendElement:presence];}//下线的方法- (void) outLine {        XMPPPresence *presence = [XMPPPresence presenceWithType:@"unavailable"];//unavailable 离线的意思    //发送离线状态    [self.stream sendElement:presence];    }//查询好友列表/** <iq from='guojing@wxhl' type='get' id='roster_1' to='域名'>    <query xmlns='jabber:iq:roster'/> <!-- iq 信息有多种,根据命名空间来区分--> </iq> */- (void) loadFriendList :(FentchFriendList) fentchFriendList {        self.fentchFriendList  = fentchFriendList;    //创建xml片段    //创建<iq></iq>    NSXMLElement *iqElement = [NSXMLElement elementWithName:@"iq"];    XMPPJID *jid = self.stream.myJID;    [iqElement addAttributeWithName:@"from" stringValue:[jid description]];    //jid.domain  ---> 服务器的域名    [iqElement addAttributeWithName:@"to" stringValue:jid.domain];    [iqElement addAttributeWithName:@"type" stringValue:@"get"];    [iqElement addAttributeWithName:@"id" stringValue:@"123456"];        //创建子节点    NSXMLElement *queryElement = [NSXMLElement elementWithName:@"query" xmlns:@"jabber:iq:roster"];    //给iq节点增加子节点.    [iqElement addChild:queryElement];    //发送请求(好友列表)    [self.stream sendElement:iqElement];}//发送消息//发送消息的格式/** <message    to='huangrong@wxhl'    from='guojing@wxhl'    type='chat'        xml:lang='en'>    <body>有个bug帮我看下</body> </message> */- (void) sendMessage:(NSString *)message toUser:(NSString *) jid {        //NIL    if (!message || [message isEqualToString:@""]) {        return;    }        NSXMLElement *messageElement = [NSXMLElement elementWithName:@"message"];        [messageElement addAttributeWithName:@"to" stringValue:jid];    XMPPJID *myJid = self.stream.myJID;    [messageElement addAttributeWithName:@"from" stringValue:myJid.description];        [messageElement addAttributeWithName:@"type" stringValue:@"chat"];        [messageElement addAttributeWithName:@"xml:lang" stringValue:@"en"];    //<message></message>创建完毕    //创建子节点<body></body>    NSXMLElement *bodyElement = [NSXMLElement elementWithName:@"body" stringValue:message];    [messageElement addChild:bodyElement];        //发送消息    [self.stream sendElement:messageElement];}//注销方法- (void) logOutAction : (LogoutSuccessBlock) block {    //发送离线的消息    [self outLine];        //断开连接,主动断开链接    [self.stream disconnect];        if (block) {        block();    }}//注册的方法- (void) registerUser:(NSString *)userName password:(NSString *)password registerSuccessBlock:(RegisterSuccessBlock) block {    _connectType = kTypeRegister;    //连接    self.userName = userName;    self.password = password;    self.registerBlock = block;        [self connect];}#pragma mark - XMPP DELEGAET- (void)xmppStreamDidConnect:(XMPPStream *)sender {    NSLog(@"连接成功");    //注册流程和登录流程都要使用该方法.在这里就要进行逻辑上判断    if (_connectType == kTypeRegister) {        [self.stream registerWithPassword:self.password error:nil];    }else if(_connectType == kTypeLogin){        //如果连接成功,则继续验证密码.        [self.stream authenticateWithPassword:self.password error:nil];    }}//验证成功的方法- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender {    NSLog(@"验证成功");    //要调用成功的block    //发送上线的状态.    [self online];    if (self.loginSuccessBlock) {        self.loginSuccessBlock();    }}//验证失败的方法- (void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(NSXMLElement *)error {    NSLog(@"验证失败");    //如果认证失败的话,要主动断开连接    [self.stream disconnect];    if (self.loginFailBlock) {        self.loginFailBlock(@"密码错误");    }}//获取查询信息- (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq {    /**     //根节点     <iq xmlns="jabber:client" type="result" id="123456" to="1234@zy/f54fcd02">        <query xmlns="jabber:iq:roster">            <item jid="gxb@localhost" name="" ask="subscribe" subscription="none">                <group>联系人列表</group>            </item>            <item jid="laoyan@zy" name="laoyan" subscription="both">                <group>12</group>            </item>            <item jid="deskmate@zy" name="deskmate" subscription="both">                <group>12</group>                <group>12</group>            </item>            <item jid="test123@zy" name="test123" subscription="both">                <group>联系人列表</group>            </item>            <item jid="zhengqingqing@192.168.13.12" name="" ask="subscribe" subscription="none">                <group>联系人列表</group>            </item>            <item jid="liuweiwei@zy" name="" subscription="both">                <group>让你变绿</group>                <group>让你变绿</group>            </item>            <item jid="zhengqingqing@zy" name="zhengqingqing" subscription="both">                <group>让你变绿</group>            </item>            <item jid="gxb1@zy" name="" subscription="both">                <group>联系人列表</group>                <group>联系人列表</group>                <group>变绿了</group>            </item>            <item jid="123456@localhost" name="" ask="subscribe" subscription="none">                <group>联系人列表</group>            </item>        </query>     </iq>     */    //需要要类型是 字典    /**     dic = {        "联系人列表":[user1,user3],        "12":[user2]     }     */    NSMutableDictionary *results = [NSMutableDictionary dictionary];    NSXMLElement *queryElement = iq.childElement;    //遍历Query节点    User *user = nil;    for (NSXMLElement *itemElement in queryElement.children) {                user = [[User alloc] init];                NSString *jidString = [itemElement attributeStringValueForName:@"jid"];                user.jid = jidString;                NSString *userName = [itemElement attributeStringValueForName:@"name"];                user.username = userName;                for (NSXMLElement *groupElement in itemElement.children) {            //组名 12            NSString *groupString = groupElement.stringValue;                        NSMutableArray *users = results[groupString];                        if (users == nil) {                users = [NSMutableArray array];                results[groupString] = users;            }            [users addObject:user];        }    }        if (self.fentchFriendList) {        self.fentchFriendList(results);    }            NSLog(@"获取好友列表 %@",results);    return YES;}//监听外部传过来的数据,就是如果有好友发来信息,则,回调此方法./** //传过来很多message标签,我们只需要带body的message标签 <message xmlns="jabber:client" type="chat" id="purplea775e98a" to="1234@zy" from="gxb1@zy/MacdeMacBook-Pro-3"><composing xmlns="http://jabber.org/protocol/chatstates"/></message> 2015-11-18 09:35:20.264 WeChat[3162:161262] message is <message xmlns="jabber:client" type="chat" id="purplea775e98b" to="1234@zy" from="gxb1@zy/MacdeMacBook-Pro-3"><active xmlns="http://jabber.org/protocol/chatstates"/><body>sad</body></message> 2015-11-18 09:35:30.491 WeChat[3162:161262] message is <message xmlns="jabber:client" type="chat" id="purplea775e98c" to="1234@zy" from="gxb1@zy/MacdeMacBook-Pro-3"><active xmlns="http://jabber.org/protocol/chatstates"/></message> */- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message {    //判断当前的message标签是否带body子标签    if ([message isChatMessageWithBody]) {        NSString *body = message.body;        //获取发信息的人的jid        XMPPJID *jidFrom = message.from;                        NSDictionary *messageDic = @{                                     @"fromUser":jidFrom.description,                                     @"text":body                                     };                //通知,发出接收消息的通知        [[NSNotificationCenter defaultCenter] postNotificationName:kRecevieMessageNotification object:nil userInfo:messageDic];            }        }//注册成功调用的方法- (void)xmppStreamDidRegister:(XMPPStream *)sender {    _connectType = kTypeLogin;    self.loginSuccessBlock = self.registerBlock;    self.registerBlock = nil;    [self xmppStreamDidConnect:sender];}@end

把宏定义改成自己的参数,在相关的UI操作代码中创建  单例XMPPHelper  然后调用相关方法,并在相关的代理方法中实现必要的操作就可以了。

 


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表