你的位置:首页 > 操作系统

[操作系统]iOS中 XMPP即时通讯实现的主要步骤


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

首先导入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 */- (void) loadFriendList :(FentchFriendList) fentchFriendList {    self.fentchFriendList = fentchFriendList;  //创建//创建<iq></iq>  NS@"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"];    //创建子节点  NS@"query" @"jabber:iq:roster"];  //给iq节点增加子节点.  [iqElement addChild:queryElement];  //发送请求(好友列表)  [self.stream sendElement:iqElement];}//发送消息//发送消息的格式/** <message  to='huangrong@wxhl'  from='guojing@wxhl'  type='chat'    */- (void) sendMessage:(NSString *)message toUser:(NSString *) jid {    //NIL  if (!message || [message isEqualToString:@""]) {    return;  }    NS*messageElement = [NS@"message"];    [messageElement addAttributeWithName:@"to" stringValue:jid];  XMPPJID *myJid = self.stream.myJID;  [messageElement addAttributeWithName:@"from" stringValue:myJid.description];    [messageElement addAttributeWithName:@"type" stringValue:@"chat"];    [messageElement addAttributeWithName:@"" stringValue:@"en"];  //<message></message>创建完毕  //创建子节点<body></body>  NS@"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:(NS)error {  NSLog(@"验证失败");  //如果认证失败的话,要主动断开连接  [self.stream disconnect];  if (self.loginFailBlock) {    self.loginFailBlock(@"密码错误");  }}//获取查询信息- (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq {  /**   //根节点   <iq */  //需要要类型是 字典  /**   dic = {    "联系人列表":[user1,user3],    "12":[user2]   }   */  NSMutableDictionary *results = [NSMutableDictionary dictionary];  NS*queryElement = iq.childElement;  //遍历Query节点  User *user = nil;  for (NSin queryElement.children) {        user = [[User alloc] init];        NSString *jidString = [itemElement attributeStringValueForName:@"jid"];        user.jid = jidString;        NSString *userName = [itemElement attributeStringValueForName:@"name"];        user.username = userName;        for (NSin 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 http://jabber.org/protocol/chatstates"/></message> 2015-11-18 09:35:20.264 WeChat[3162:161262] message is <message http://jabber.org/protocol/chatstates"/><body>sad</body></message> 2015-11-18 09:35:30.491 WeChat[3162:161262] message is <message 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  然后调用相关方法,并在相关的代理方法中实现必要的操作就可以了。