前言:這兩天看了XMPP框架,查閱了一些資料,寫下這篇文章記錄一下學習筆記
一、簡要解析XMPP核心部分
XMPP框架分為兩個部分
1.核心部分
2.擴展部分
擴展部分主要講好友列表(roster)、自動重連(automatic reconnect)、還有一些其他的實現。
核心部分包括以下部分:
- XMPPStream
- XMPPParser
- XMPPJID
- XMPPElement
- XMPPIQ
- XMPPMessage
- XMPPPresence
- XMPPModule
- XMPPLogging
- XMPPInternal
1.XMPPStream
XMPPStream類相當於輸入輸出流,用於連接服務器並發送消息。
XMPPStream添加和移除代理寫了方法
1 - (void)addDelegate:(id)delegate delegateQueue:(dispatch_queue_t)delegateQueue; 2 - (void)removeDelegate:(id)delegate delegateQueue:(dispatch_queue_t)delegateQueue; 3 - (void)removeDelegate:(id)delegate;
XMPP底層就是socket,所以XMPPStream實現了socket協議<GCDAsyncSocketDelegate>
初始化方法
- (id)init { if ((self = [super init])) { // Common initialization [self commonInit]; // Initialize socket asyncSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:xmppQueue]; } return self; }
XMPPStream包含的一些屬性
/** Jabber ID 用於表示用戶身份的地址 */ @property (readwrite, copy) XMPPJID *myJID;
/** 要連接的服務器的域名 格式為talk.google.com */
@property (readwrite, copy) NSString *hostName;
/** 要連接的服務器的端口號 默認為5222*/
@property (readwrite, assign) UInt16 hostPort;
2.XMPPParser
XMPPParser,是XMPPStream的解析器,解析傳遞的信息
3.XMPPJID
在XMPP協議中表示一個地址,由以下三個部分組成
node/username:表示一個向服務器或網關和使用網絡服務的實體(節點、用戶名,用戶的基本標識)
domain:表示網絡中的網關或者服務器(例如一個JID,username@domain/resource,domian即后面的域名)
resource:表示一個特定的回話(或者某個設備),連接(或地址),或者一個附屬於某個節點ID實體相關的實體對象(或者多人聊天室中的參與者),可用於區分用戶的設備等
還有定義的其他屬性,
Bare:就是node+domain,username@domain,即JID除去resource
Full:一個完整的JID,包含username,domain,resource,比Bare多了resource
XMPPJID源碼的一個枚舉,看數字和,很好理解
enum XMPPJIDCompareOptions { XMPPJIDCompareUser = 1, // 001 XMPPJIDCompareDomain = 2, // 010 XMPPJIDCompareResource = 4, // 100 XMPPJIDCompareBare = 3, // 011 XMPPJIDCompareFull = 7, // 111 };
XMPPJID使用了解檔,歸檔,遵守了<NSCoding, NSCopying>協議
4.XMPPElement
XMPPElement是3個基本元素(IQ,Message,Presence)的基類
繼承自NSXMLElement
配合分類NSXMLElement+XMPP使用可以讓代碼更簡潔和提高可讀性
5.XMPPIQ
請求
主要屬性是type(Message和Presence一樣,表示請求或者消息的類型)
<iq Type="result"
from="lightman@google.com/contact"
to="google.com"
id = '123456'>
<query xmins="jabber:iq:roster"/>
<iq/>
type屬性:說明了該iq類型為get,像服務端請求信息
from屬性:小心來源,=JID
to屬性:消息目標,=服務器域名
id屬性,可選,標記該請求ID,當服務器處理完畢請求get類型的iq后,響應的result類型iq和ID與請求iq的ID相同
6.Message
<message />節定義了消息語義,<message />節可被看作“推”機制,與Email系統中發生的通信類似。所有消息節應該擁有‘to’屬性,指定有意的消息接收者
message用於“發送后即忘”的傳輸(發送后不驗證消息是否接收成功),這樣的傳輸主要應用與人類可讀的文本、警告、通知等信息。
<message to="lightman@google.com/contact" type="chat"> <body> hello < body/> <meesage/>
7.Presence
<presence from=""> <show>顯示的內容<show/> <status>顯示的狀態<status/> <presence/>
presence的狀態
available上線
away離開
do not disturb忙碌
unavailable 下線
二、導入XMPP框架
XMPP在github-wiki上說明的步驟過期了
但是給出了指向stack flow回答的連接
http://stackoverflow.com/questions/9091767/up-to-date-instructions-on-how-to-install-xmppframework-manually/30543948#30543948
步驟1
必須導入Xcode的文件夾
- Vendor/CocoaAsyncSocket
- Vendor/CocoaLumberjack
- Vendor/KissXML
- Vendor/libidn
- Authentication
- Categories
- Core
- Utilities
也可以導入Extensions,可選
導入的時候要選擇復制進項目中
步驟2
導入頭文件XMPPFramework.h,也要賦值選項
導入完的框架
步驟3
要導入以下的自帶框架和庫
- CFNetwork.framework
- Security.framework
- libxml2.dylib
- libresolv.dylib
- libidn.a
注意,在項目Xcode8之后的Xcode9 庫的dylib后綴名改為thd,可能要重新導入
步驟4
Build Settings中要添加
other linker flags = -lxml2
HEADER SEARCH PATHS = /usr/include/libxml2
注意最后還要導入<UIKit/UIkit.h>
三、簡要使用XMPP框架
這里省略配置服務器(用的是openfire)和數據庫(mysql)步驟,網上很多教程
步驟1 連接服務器
- (void)connect {
// 創建XMPPStream if (self.xmppStream == nil) { self.xmppStream = [[XMPPStream alloc] init]; [self.xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()]; }
//設置JID 然后使用XMPPStream連接服務器 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]); } } }
連接成功后悔調用XMPPStreamDelegate的方法
首先會調用
- (void)xmppStream:(XMPPStream *)sender socketDidConnect:(GCDAsyncSocket *)socket
然后會調用
- (void)xmppStreamDidConnect:(XMPPStream *)sender
步驟2
連接成功后,發送密碼授權
-(void)sendPwdToHost{ NSError *err = nil; //YBUserInfo是自定義數據類型,用於存儲用戶名、密碼等屬性 // 從單例里獲取密碼 NSString *pwd = [YBUserInfo sharedWCUserInfo].pwd; //使用XMPPStream發送密碼 [_xmppStream authenticateWithPassword:pwd error:&err]; if (err) { NSLog(@"%@",err); } }
步驟3
授權成功后,發送消息
-(void)sendOnlineToHost{
XMPPPresence *presence = [XMPPPresence presence];
[_xmppStream sendElement:presence];
}
與服務器斷開連接會調用代理方法
-(void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error
授權成功會調用方法
-(void)xmppStreamDidAuthenticate:(XMPPStream *)sender
授權失敗會調用方法
-(void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(DDXMLElement *)error
注冊成功會調用方法
-(void)xmppStreamDidRegister:(XMPPStream *)sender
注冊失敗會調用方法
-(void)xmppStream:(XMPPStream *)sender didNotRegister:(DDXMLElement *)error
退出並斷開連接
- (void)disconnect { XMPPPresence *presence = [XMPPPresence presenceWithType:@"unavailable"]; [self.xmppStream sendElement:presence]; [self.xmppStream disconnect]; }
寫這篇博文目的是加深自己對XMPP的理解
查了一些資料,很多都是全英的,還是要學好英語
轉載請注明出處