改定履曆:
2011-08-19-------------------建立文本文檔
2011-08-25--------------------增加XMPP官網連結
2011-09-02-------------------新增對GLOOX1.0API文檔Main Page頁翻譯
個人研究XMPP已經有大約一個星期的時間了,基本過程是先看了三天的RFC,包括RFC3290,RFC3291兩個主要協定,然後就是研究GLOOX1.0了。XMPP除了這兩個核心協定之外還有很多的XEP擴充協定。另外比較成熟的XMPP協定棧是GLOOX1.0版。前文已經貼出了RFC文檔,從這篇文章開始詳細介紹GLOOX,由于本人也是邊學邊記錄,有高手飄過時請不吝賜教。
先貼出一下XMPP一些相關資源:
XMPP官網
gloox官方網站---這裡可以了解gloox的官方資訊,開發文檔等
gloox1.0API文檔---個人将官方的API文檔整站下載下傳下來打包,友善本地檢視,強烈建議大家詳細看一下文檔的Main Page頁,以對整個gloox的設計有一個大的層面上的了解
RFC3920------XMPP核心協定
RFC3921------即時消息和出席資訊
xmpp協定PPT----XMPP PPT文檔
先這些吧,以後随時補充
---------------------------------------------------------------------------------------------------------------------
GLOOX協定棧是基于所謂“觀察者”設計模式設計的,如果你熟悉“觀察者”設計模式或者不熟悉但是在去深入了解GLOOX之前能去看一下“觀察者”模式會對學習GLOOX很有好處。其主要思想就是将觀察者“注冊”到“被觀察者”那裡,“被觀察者”有什麼風吹草動,觀察者都會知道,而進一步的處理就是在你的程式裡實作“觀察者”的若幹虛函數。
環境搭建的話,本人用的是vs2008,下載下傳下來gloox1.0,建立一個工程把gloox下src目錄裡所有的.h和.cpp全部加載,再添加一個工程用于對gloox進行測試,将兩個工程的生成目錄及依賴設定好即可。
----------------------------------------------------------------------------------------------------------------------
補充:部落客近日學習GLOOX,重讀了API Main Page頁,覺得Main Page頁對于新手從較高層面上把握GLOOX有很大幫助,且這裡往往是新手容易忽略的最直接的一手資料資訊來源,于是決定花時間翻譯出來。限于本人英文水準,大家可參照原英文文檔檢視:
Introduction:
GLOOX的設計遵循了所謂的觀察者設計模式,含義是一切都是基于事件驅動的。使用GLOOX不如Jabber/XMPP網絡有兩種方式------做為用戶端或元件。C++ XMPP伺服器庫請參考<http://camaya.net/glooxd>.
Note:
XMPP詳細規格說明書(RFC 3290)的11.5小節要求,線路上交換的資料隻能是UTF-8編碼方式,由于GLOOX不知道輸入的資料是哪種編碼,是以GLOOX要求輸入資料必須是有效的UTF-8編碼。
Event Handlers:
GLOOX裡最重要的工具就是事件處理器(event hanbdlers),目前,除了有為RFC中定義的基本協定服務的4種事件處理器,還有為XEP實作裡的事件和附加功能服務的其它許多事件處理器。另外,一個日志處理器、一個一般标簽處理器和一個連接配接事件處理器都是有效的。
通常這些處理器都是虛接口,你可以繼承它們派生出一個類,并且實作一些這些虛函數。然後你可以注冊這樣的一個子類對象到各自的協定實作裡。下面是一個簡單的例子:
[cpp] view plain copy
- class MyClass : public PresenceHandler
- {
- public:
- // reimplemented from PresenceHandler
- virtual void handlePresence(const Presence& presence );
- [...]
- };
- void MyClass::handlePresence( const Presence& presence )
- {
- // extract further information from the Presence object
- }
在某個地方你可以像下面這樣做: [cpp] view plain copy
- OtherClass::doSomething()
- {
- Client* client = new Client( ... );
- [...]
- MyClass* handler = new MyClass( ... );
- client->registerPresenceHandler( handler );
- }
然後你可以使用Stanza類提供的衆多getters(即get字首的成員函數)進一步提取節中的資料
現在,每次接收到一個presence節(非subscription節)時,handlePresence都會被調用,參數是目前節。然後你可以使用Stanza類提供的衆多getters(一般來講是get字首的方法,此處了解為擷取stanza各資料的方法)進一步提取節中的資料以進一步處理。
幾乎是以的事件處理器的工作方式都是與這個例子相似的,接下來以使用連接配接事件處理器(class ConnectionListener)為例,再舉一例:
[cpp] view plain copy
- class MyClass : public ConnectionListener
- {
- public:
- virtual void onConnect();
- virtual bool onTLSConnect( ... );
- };
- void MyClass::onConnect()
- {
- // do something when the connection is established
- }
- bool MyClass::onTLSConnect( const CertInfo& info )
- {
- // decide whether you trust the certificate, examine the CertInfo structure
- return true; // if you trust it, otherwise return false
- }
Note:
ConnectionListener是一個比較奇特的接口。你必須重新實作ConnectionListener::onTLSConnect()這個接口,如果你想成功連接配接一個啟用了TLS/SSL伺服器的話。盡管GLOOX試圖檢查伺服器的證書,但不會自動的信任該伺服器。必須由用戶端程式員或使用者來決定是否信任此伺服器。是否信任就由onTLSConnect()的傳回值來表示,FLASE意味着你不信任該伺服器,結果就是與伺服器的連接配接中斷。
先去吃飯了,回來待續……
Components
Jabber/XMPP網絡中的一個元件是加載到伺服器上的,它運作在實際的服務軟體之外,但它有相似的權限,元件使用XEP-0114中描述的協定去連接配接和驗證一個伺服器.類Component 支援該協定并且可以用于建立一個新的Jabber component.簡單的例子如下:
[cpp] view plain copy
- Component* comp = new Component( ... );
- comp->connect();
Clients
一個用戶端可以是終端使用者的聊天用戶端,一個機器人或者是一個沒有和特殊伺服器綁定在一起的簡單實體。類Client實作了連接配接一個XMPP 伺服器所需要的功能。一個例子如下:
[cpp] view plain copy
- class MyClass : public ConnectionListener, PresenceHandler
- {
- public:
- void doSomething();
- virtual void handlePresence( ... );
- virtual void onConnect();
- virtual bool onTLSConnect( const CertInfo& info );
- };
- void MyClass::doSomething()
- {
- JID jid( "[email protected]/resource" );
- Client* client = new Client( jid, "password" );
- client->registerConnectionListener( this );
- client->registerPresenceHandler( this );
- client->connect();
- }
- void MyClass::onConnect()
- {
- // connection established, auth done (see API docs for exceptions)
- }
- bool MyClass::onTLSConnect( const CertInfo& info )
- {
- // examine certificate info
- }
- void MyClass::handlePresence( Presence* presence )
- {
- // presence info
- }
Note
GLOOX官方并不支援5223上的連接配接方式。例如:在XML串先于SSL加密之前被發送,因為這是曆史遺留的方法況且不符合标準的XMPP協定。然而,GLOOX提供了一個ConnectionTlS類,做為附加功能,允許你去綁定一個這樣的連接配接。
預設情況下,Client::connect()是阻塞的,直到連接配接終止(Client::disconnect()被調用,或者伺服器終止連接配接)。
阻塞和非阻塞連接配接
對于某些種類的機器人來說阻塞式的連接配接(預設的行為)是非常理想的方式。幾乎所有的機器人都是對來自于伺服器的事件做出響應。然而,對某些終端使用者或帶有GUI應用的用戶端來說就不那麼完美了。
這些情況下就需要用到非阻塞式的連接配接了。如果調用ClinetBase::connect(false),函數将會在綁定連接配接後立即傳回。接下來程式員就有責任初始化一些從SOCKET接收到的資料。
一種最簡單的方法是以一個逾時值(微秒)做為參數周期性的調用ClientBase::recv(),預設值-1意味着調用是阻塞的,直到有資料到達,對資料的解析也是自動的。
作為周期性地輪詢一種替換辦法,你可以擷取連接配接的原始檔案描述符。你可以在該檔案描述符上使用select()并且當select上的資料有效時使用ClientBase::recv()。你可能直接從檔案描述符得不到任何資料,也沒有辦法為解析器提供資料。
為了得到檔案描述符,你必須手動設定一個連接配接類(ConnectionTCPClient),就像這樣:
[cpp] view plain copy
- Client* client = new Client( ... );
- ConnectionTCPClient* conn = new ConnectionTCPClient( client, client->logInstance(), server, port );
- client->setConnectionImpl( conn );
- client->connect( false );
- int sock = conn->socket();
- [...]
有可能像下面這樣擷取檔案描述符: [cpp] view plain copy
- Client* client = new Client( ... );
- client->connect( false );
- int sock = static_cast<ConnectionTCPClient*>( client->connectionImpl() )->socket();
- [...]
顯然,隻要你沒有使用setConnectionImpl()設定一個不同的連接配接類型就會工作。
Note
在0.9以後的版本裡這已經發生了改變,ClientBase::fileDescriptor()不在可用了。
Roster Management
RFC3921定義了如何管理一個人的聯系清單(花名冊)。在GLOOX中,類RosterManager實作了這個功能。一組簡單函數有效地實作了訂閱和取消訂閱實體的出席。也可以在沒有實際訂閱此聯系人出席的情況,把他加入到自己的花名冊中。另外,接口RosterListener對應于各種花名冊相關的事件提供了一組回調函數。
如果你依上所述建立了一個用戶端對象,那麼你可以擷取一個RosterManager對象。Client::rosterManager()傳回一個該類對象的指針。
Privacy Lists
同樣地,“隐私清單”也定義在RFC3921中,一個隐秘清單可以明确地禁止或允許 從聯系人接收或發給聯系人資料節,區分不同的聯系人。你可以自己定義基于JID,節類型等的規則。類PrivacyManager 和類PrivacyListHandler虛接口在隐私清單的處理上比較靈活。
[cpp] view plain copy
- PrivacyManager* p = new PrivacyManager( ... );
- [...]
- PrivacyListHandler::PrivacyList list;
- PrivacyItem item( PrivacyItem::TypeJid, PrivacyItem::ActionDeny,
- PrivacyItem::PacketMessage, "[email protected]" );
- list.push_back( item );
- PrivacyItem item2( PrivacyItem::TypeJid, PrivacyItem::ActionAllow,
- PrivacyItem::PacketIq, "[email protected]" );
- list.push_back( item2 );
- p->store( "myList", list );
Authentication
GLOOX支援XEP-0078定義的舊樣式的基于IQ節的鑒權機制,也支援若幹SASL機制。可以參考Client類文檔說明以擷取更多資訊。
Sending and Receiving of Chat Messages
對于消息傳輸推薦使用MessageSession接口。它處理消息的發送和接收,也處理包括消息事件和聊天狀态(例如“打字中……”)等。檢視MessageSession類文檔以擷取更多細節。
Protocol Extensions (XEPs)
XMPP标準基金會釋出了許多核心協定的擴充,稱為XMPP Extension Protocols(XEPs)(XMPP擴充協定)。一些擴充協定已經在GLOOX中得到實作:
XEP-0004 Data Forms
XEP-0012 Last Activity
XEP-0013 Flexible Offline Message Retrieval
XEP-0022 Message Events (see MessageSession for examples)
XEP-0027 Current Jabber OpenPGP Usage (see GPGSigned and GPGEncrypted )
XEP-0030 Service Discovery
XEP-0045 Multi-User Chat
XEP-0047 Used with File Transfer
XEP-0048 Bookmark Storage
XEP-0049 Private XML Storage
XEP-0050 Ad-hoc Commands
XEP-0054 vcard-temp
XEP-0060 Publish-Subscribe
XEP-0065 SOCKS5 Bytestreams , used with File Transfer and HTTP and SOCKS5 Proxy support
XEP-0066 Out of Band Data , also used with File Transfer
XEP-0077 In-Band Registration
XEP-0078 Non-SASL Authentication (automatically used if the server does not support SASL)
XEP-0079 Advanced Message Processing
XEP-0083 Nested Roster Groups (automatically used if supported by the server. see RosterManager )
XEP-0085 Chat State Notifications (see MessageSession for examples)
XEP-0091 Delayed Delivery (old spec)
XEP-0092 Software Version (integrated into Service Discovery )
XEP-0095 Stream Initiation , used with File Transfer
XEP-0096 File Transfer
XEP-0106 JID Escaping
XEP-0114 Jabber Component Protocol
XEP-0115 Entity Capabilities (used automatically internally)
XEP-0124 Bidirectional-streams Over Synchronous HTTP (BOSH)
XEP-0131 Stanza Headers and Internet Metadata
XEP-0138 Stream Compression (used automatically if gloox is compiled with zlib and if the server supports it)
XEP-0145 Annotations
XEP-0153 vCard-based Avatars
XEP-0172 User Nickname
XEP-0184 Message Receipts
XEP-0199 XMPP Ping
XEP-0203 Delayed Delivery (new spec)
XEP-0206 see BOSH
XEP-0224 Attention
XEP-0256 Last Activity in Presence
更進一步的擴充可以用類StanzaExtensions很容易的實作。
File Transfer
對于檔案傳輸,GLOOX實作了XEP-0095(流初始化協定)和XEP-0096(檔案傳輸)協定的信号機制;為傳輸實作了XEP-0065(SOCKS5 Bytestreams 流位元組)和XEP-0047(帶内位元組流)。參考 SIProfileFT類
HTTP and SOCKS5 Proxy support
gloox 有能力穿過http及SOCKS5代理,即便是連鎖代理。參考ConnectionHTTPProxy類 和 ConnectionSocks5Proxy類.
分享到: