XMPPFramework核心類介紹
XMPPFramework結構
在進入下一步之前,先給大家講講XMPPFramework的目錄結構,以便新手們更容易讀懂文章。我們來看看下圖:
雖然這裏有很多個目錄,但是我們在開發中基本只關心Core和Extensions這兩個目錄下的類。各個目錄主要用來幹嘛的?
- Authentication:這一看名字就知道與授權驗證相關的。
- Categories:主要是一些擴展,尤其是NSXMLElement+XMPP擴展是必備的。
- Core:這裏是XMPP的核心文件目錄,我們最主要的目光還是要放在這個目錄上。
- Extensions:這個目錄是XMPP的擴展,用於擴展各種協議和各種獨立的功能,其下每個子目錄都是對應的一個單獨的子功能。我們最常用到的功能有Reconnect、Roster、CoreDataStorage等。
- Utilities:都是輔助類,我們開發者不用關心這裏。
- Vendor:這個目錄是XMPP所引用的第三方類庫,如CocoaAsyncSocket、KissXML等,我們也不用關心這裏。
閱讀到此,對XMPPFramework的結構有所了解了吧!
概念知識
登錄需要到賬號,而所謂的賬號其實就是用戶唯一標識符(JID),在XMPP中使用XMPPJID類來表示。那麽,用戶唯一標識(JID)有什麽組成?
JID一般由三部分構成:用戶名,域名和資源名,[email protected]/resource,例如: [email protected] /Anthony。對應於XMPPJID類中的三個屬性user、domain、resource。
如果沒有設置主機名(HOST),則使用JID的域名(domain)作為主機名,而端口號是可選的,默認是5222,一般也沒有必要改動它。
XMPPStream類
我們要與服務器連接,就必須通過XMPPStream類了,它提供了很多的API和屬性設置,通過socket來實現的。我們看到Verdor目錄了嗎,包含了CocoaAsyncSocket這個非常有名的socket編程庫。XMPPStream類還遵守並實現了GCDAsyncSocketDelegate代理,用於客戶端與服務器交互。
@interface XMPPStream : NSObject <GCDAsyncSocketDelegate>
當我們創建XMPPStream對象後,我們需要設置代理,才能回調我們的代理方法,這個是支持multicast delegate,也就是說對於一個XMPPStream對象,可以設置多個代理對象,其中協議是XMPPStreamDelegate:
- (void)addDelegate:(id)delegatedelegateQueue:(dispatch_queue_t)delegateQueue;
而當我們不希望某個XMPPStream對象繼續接收到代理回調時,我們通過這樣的方式來移除代理:
- (void)removeDelegate:(id)delegatedelegateQueue:(dispatch_queue_t)delegateQueue;
- (void)removeDelegate:(id)delegate;
接下來,我們要設置主機和端口,通過設置這兩個屬性:
/**
* The server‘s hostname that should be used to make the TCP connection.
* 註釋太長,簡單說就是主機。這個屬性是可選設置的,如果沒有設置主機,默認會使用domain
*/
@property (readwrite, copy) NSString *hostName;
/**
* The port the xmpp server is running on.
* If you do not explicitly set the port, the default port will be used.
* If you set the port to zero, the default port will be used.
*
* The default port is 5222.
**/
@property (readwrite, assign) UInt16 hostPort;
XMPPStream有XMPPJID類對象作為屬性,標識用戶,因為我們後續很多操作都需要到myJID:
@property (readwrite, copy) XMPPJID *myJID;
而管理用戶在線狀態的就交由XMPPPresence類了,它同樣被作為XMPPStream的屬性,組合到XMPPStream中,後續很多關於用戶的操作是需要到處理用戶狀態的:
/**
* Represents the last sent presence element concerning the presence of myJID on the server.
* In other words, it represents the presence as others see us.
*
* This excludes presence elements sent concerning subscriptions, MUC rooms, etc.
*
* @see resendMyPresence
**/
@property (strong, readonly) XMPPPresence *myPresence;
XMPPStreamDelegate
這個協議是非常關鍵的,我們的很多主要操作都集中在這個協議的代理回調上。它分為好幾種類型的代理API,比如授權的、註冊的、安全的等:
@protocol XMPPStreamDelegate
@optional
// 將要與服務器連接是回調
- (void)xmppStreamWillConnect:(XMPPStream *)sender;
// 當tcp socket已經與遠程主機連接上時會回調此代理方法
// 若App要求在後臺運行,需要設置XMPPStream‘s enableBackgroundingOnSocket屬性
- (void)xmppStream:(XMPPStream *)sendersocketDidConnect:(GCDAsyncSocket *)socket;
// 當TCP與服務器建立連接後會回調此代理方法
- (void)xmppStreamDidStartNegotiation:(XMPPStream *)sender;
// TLS傳輸層協議在將要驗證安全設置時會回調
// 參數settings會被傳到startTLS
// 此方法可以不實現的,若選擇實現它,可以可以在
// 若服務端使用自簽名的證書,需要在settings中添加GCDAsyncSocketManuallyEvaluateTrust=YES
//
- (void)xmppStream:(XMPPStream *)senderwillSecureWithSettings:(NSMutableDictionary *)settings;
// 上面的方法執行後,下一步就會執行這個代理回調
// 用於在TCP握手時手動驗證是否受信任
- (void)xmppStream:(XMPPStream *)senderdidReceiveTrust:(SecTrustRef)trust
completionHandler:(void (^)(BOOL shouldTrustPeer))completionHandler;
// 當stream通過了SSL/TLS的安全驗證時,會回調此代理方法
- (void)xmppStreamDidSecure:(XMPPStream *)sender;
// 當XML流已經完全打開時(也就是與服務器的連接完成時)會回調此代理方法。此時可以安全地與服務器通信了。
- (void)xmppStreamDidConnect:(XMPPStream *)sender;
// 註冊新用戶成功時的回調
- (void)xmppStreamDidRegister:(XMPPStream *)sender;
// 註冊新用戶失敗時的回調
- (void)xmppStream:(XMPPStream *)senderdidNotRegister:(NSXMLElement *)error;
// 授權通過時的回調,也就是登錄成功的回調
- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender;
// 授權失敗時的回調,也就是登錄失敗時的回調
- (void)xmppStream:(XMPPStream *)senderdidNotAuthenticate:(NSXMLElement *)error;
// 將要綁定JID resource時的回調,這是授權程序的標準部分,當驗證JID用戶名通過時,下一步就驗證resource。若使用標準綁定處理,return nil或者不要實現此方法
- (id <XMPPCustomBinding>)xmppStreamWillBind:(XMPPStream *)sender;
// 如果服務器出現resouce沖突而導致不允許resource選擇時,會回調此代理方法。返回指定的resource或者返回nil讓服務器自動幫助我們來選擇。一般不用實現它。
- (NSString *)xmppStream:(XMPPStream *)senderalternativeResourceForConflictingResource:(NSString *)conflictingResource;
// 將要發送IQ(消息查詢)時的回調
- (XMPPIQ *)xmppStream:(XMPPStream *)senderwillReceiveIQ:(XMPPIQ *)iq;
// 將要接收到消息時的回調
- (XMPPMessage *)xmppStream:(XMPPStream *)senderwillReceiveMessage:(XMPPMessage *)message;
// 將要接收到用戶在線狀態時的回調
- (XMPPPresence *)xmppStream:(XMPPStream *)senderwillReceivePresence:(XMPPPresence *)presence;
/**
* This method is called if any of the xmppStream:willReceiveX: methods filter the incoming stanza.
*
* It may be useful for some extensions to know that something was received,
* even if it was filtered for some reason.
**/
// 當xmppStream:willReceiveX:(也就是前面這三個API回調後),過濾了stanza,會回調此代理方法。
// 通過實現此代理方法,可以知道被過濾的原因,有一定的幫助。
- (void)xmppStreamDidFilterStanza:(XMPPStream *)sender;
// 在接收了IQ(消息查詢後)會回調此代理方法
- (BOOL)xmppStream:(XMPPStream *)senderdidReceiveIQ:(XMPPIQ *)iq;
// 在接收了消息後會回調此代理方法
- (void)xmppStream:(XMPPStream *)senderdidReceiveMessage:(XMPPMessage *)message;
// 在接收了用戶在線狀態消息後會回調此代理方法
- (void)xmppStream:(XMPPStream *)senderdidReceivePresence:(XMPPPresence *)presence;
// 在接收IQ/messag、presence出錯時,會回調此代理方法
- (void)xmppStream:(XMPPStream *)senderdidReceiveError:(NSXMLElement *)error;
// 將要發送IQ(消息查詢時)時會回調此代理方法
- (XMPPIQ *)xmppStream:(XMPPStream *)senderwillSendIQ:(XMPPIQ *)iq;
// 在將要發送消息時,會回調此代理方法
- (XMPPMessage *)xmppStream:(XMPPStream *)senderwillSendMessage:(XMPPMessage *)message;
// 在將要發送用戶在線狀態信息時,會回調此方法
- (XMPPPresence *)xmppStream:(XMPPStream *)senderwillSendPresence:(XMPPPresence *)presence;
// 在發送IQ(消息查詢)成功後會回調此代理方法
- (void)xmppStream:(XMPPStream *)senderdidSendIQ:(XMPPIQ *)iq;
// 在發送消息成功後,會回調此代理方法
- (void)xmppStream:(XMPPStream *)senderdidSendMessage:(XMPPMessage *)message;
// 在發送用戶在線狀態信息成功後,會回調此方法
- (void)xmppStream:(XMPPStream *)senderdidSendPresence:(XMPPPresence *)presence;
// 在發送IQ(消息查詢)失敗後會回調此代理方法
- (void)xmppStream:(XMPPStream *)senderdidFailToSendIQ:(XMPPIQ *)iqerror:(NSError *)error;
// 在發送消息失敗後,會回調此代理方法
- (void)xmppStream:(XMPPStream *)senderdidFailToSendMessage:(XMPPMessage *)messageerror:(NSError *)error;
// 在發送用戶在線狀態失敗信息後,會回調此方法
- (void)xmppStream:(XMPPStream *)senderdidFailToSendPresence:(XMPPPresence *)presenceerror:(NSError *)error;
// 當修改了JID信息時,會回調此代理方法
- (void)xmppStreamDidChangeMyJID:(XMPPStream *)xmppStream;
// 當Stream被告知與服務器斷開連接時會回調此代理方法
- (void)xmppStreamWasToldToDisconnect:(XMPPStream *)sender;
// 當發送了</stream:stream>節點時,會回調此代理方法
- (void)xmppStreamDidSendClosingStreamStanza:(XMPPStream *)sender;
// 連接超時時會回調此代理方法
- (void)xmppStreamConnectDidTimeout:(XMPPStream *)sender;
// 當與服務器斷開連接後,會回調此代理方法
- (void)xmppStreamDidDisconnect:(XMPPStream *)senderwithError:(NSError *)error;
// p2p類型相關的
- (void)xmppStream:(XMPPStream *)senderdidReceiveP2PFeatures:(NSXMLElement *)streamFeatures;
- (void)xmppStream:(XMPPStream *)