這裏只是列出實現的只要步驟,不是所有代碼。服務器
首先導入XMPPFramework,及相關配置,完成後開始。網絡
建立一個XMPPHelper 類來管理要進行的操做。dom
XMPPHelper.h文件以下ide
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 5222 14 15 @interface XMPPHelper : NSObject 16 { 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文件以下post
#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 而後調用相關方法,並在相關的代理方法中實現必要的操做就能夠了。atom