解析XMPP協(xié)議分析與應(yīng)用
掃描二維碼
隨時(shí)隨地手機(jī)看文章
XMPP是一種基于XML的協(xié)議,它繼承了在XML環(huán)境中靈活的發(fā)展性。因此,基于XMPP的應(yīng)用具有超強(qiáng)的可擴(kuò)展性。經(jīng)過(guò)擴(kuò)展以后的XMPP可以通過(guò)發(fā)送擴(kuò)展的信息來(lái)處理用戶的需求,以及在XMPP的頂端建立如內(nèi)容發(fā)布系統(tǒng)和基于地址的服務(wù)等應(yīng)用程 序。而且,XMPP包含了針對(duì)服務(wù)器端的軟件協(xié)議,使之能與另一個(gè)進(jìn)行通話,這使得開發(fā)者更容易建立客戶應(yīng)用程序或給一個(gè)配好系統(tǒng)添加功能。XMPP(可擴(kuò)展消息處理現(xiàn)場(chǎng)協(xié)議)是基于可擴(kuò)展標(biāo)記語(yǔ)言(XML)的協(xié)議,它用于即時(shí)消息(IM)以及在線現(xiàn)場(chǎng)探測(cè)。它在促進(jìn)服務(wù)器之間的準(zhǔn)即時(shí)操作。這個(gè)協(xié)議可能最終允許因特網(wǎng)用戶向因特網(wǎng)上的其他任何人發(fā)送即時(shí)消息,即使其操作系統(tǒng)和瀏覽器不同。XMPP的前身是Jabber,一個(gè)開源形式組織產(chǎn)生的網(wǎng)絡(luò)即時(shí)通信協(xié)議。XMPP目前被IETF國(guó)際標(biāo)準(zhǔn)組織完成了標(biāo)準(zhǔn)化工作。
1 XMPP的地址和數(shù)據(jù)結(jié)構(gòu)
1.1 實(shí)體地址
XMPP整體框架如圖1所示。圖中,XMPP框架的各類實(shí)體(如XMPP客戶、服務(wù)器和網(wǎng)關(guān)等)的地址稱為甲吧地址(Jabber Identifier,JID)。JID惟一確定進(jìn)行即時(shí)消息和在線狀態(tài)信息通信的獨(dú)立對(duì)象或?qū)嶓w,并可兼容其他即時(shí)通信系統(tǒng)(如MSN等)相應(yīng)的實(shí)體標(biāo)識(shí)及其在線狀態(tài)信息。其語(yǔ)法規(guī)則為:[節(jié)點(diǎn)″@″] 域名[″/″資源],其中各個(gè)域的長(zhǎng)度不能超過(guò)1 023 字節(jié),總長(zhǎng)度最大為3 071字節(jié)。
XMPP中定義了三個(gè)角色,客戶端,服務(wù)器,網(wǎng)關(guān)。通信能夠在這三者的任意兩個(gè)之間雙向發(fā)生。服務(wù)器同時(shí)承擔(dān)了客戶端信息記錄,連接管理和信息的路由功能。網(wǎng)關(guān)承擔(dān)著與異構(gòu)即時(shí)通信系統(tǒng)的互聯(lián)互通,異構(gòu)系統(tǒng)可以包括SMS(短信),MSN,ICQ等?;镜木W(wǎng)絡(luò)形式是單客戶端通過(guò)TCP/IP連接到單服務(wù)器,然后在之上傳輸XML。傳輸?shù)氖桥c即時(shí)通訊相關(guān)的指令。在以前這些命令要么用2進(jìn)制的形式發(fā)送(比如QQ),要么用純文本指令加空格加參數(shù)加換行苻的方式發(fā)送(比如MSN)。而XMPP傳輸?shù)募磿r(shí)通訊指令的邏輯與以往相仿,只是協(xié)議的形式變成了XML格式的純文本。這不但使得解析容易了,人也容易閱讀了,方便了開發(fā)和查錯(cuò)。而XMPP的核心部分就是一個(gè)在網(wǎng)絡(luò)上分片斷發(fā)送XML的流協(xié)議。這個(gè)流協(xié)議是XMPP的即時(shí)通訊指令的傳遞基礎(chǔ),也是一個(gè)非常重要的可以被進(jìn)一步利用的網(wǎng)絡(luò)基礎(chǔ)協(xié)議。所以可以說(shuō),XMPP用TCP傳的是XML流。
域名指定了實(shí)體連接的XMPP服務(wù)器。每個(gè)可用XMPP服務(wù)器都擁有一個(gè)完整域名,域名可在域名系統(tǒng)(DNS)中查找;節(jié)點(diǎn)可表示某用戶、一類應(yīng)用或某項(xiàng)服務(wù),所有節(jié)點(diǎn)都對(duì)應(yīng)一個(gè)精確的域名;資源用來(lái)識(shí)別屬于用戶的特殊對(duì)象(如設(shè)備或位置),允許一個(gè)用戶同時(shí)以多個(gè)資源與同一XMPP服務(wù)器連接。
1.2 XMPP的數(shù)據(jù)結(jié)構(gòu)
由于XMPP是基于XML的協(xié)議,因此用戶可根據(jù)自己的需要定義標(biāo)記,表述幾乎任何一種結(jié)構(gòu)化數(shù)據(jù),并可方便地創(chuàng)建定制的應(yīng)用或增加功能。
1.2.1 三個(gè)頂級(jí)XML元素
XMPP定義的3個(gè)關(guān)鍵頂級(jí)XML元素為<message/>、<presence/>和<iq/>(info/query),每個(gè)元素都可以通過(guò)屬性和名字空間包含大量數(shù)據(jù),其屬性和名字空間都是XMPP的組成部分。
<message/>元素用來(lái)包含2個(gè)XMPP實(shí)體間互相發(fā)送的消息內(nèi)容;<presence/>元素表示實(shí)體可用性信息,可用性信息有“可用”和“不可用”2種;<iq/>元素用來(lái)構(gòu)建2個(gè)實(shí)體間的會(huì)話,并且允許實(shí)體間來(lái)回傳送XML格式的請(qǐng)求和響應(yīng)以便取得或設(shè)置公共的用戶信息,如名字等。
即時(shí)通信中名字沖突問(wèn)題使用XML的命名空間特性來(lái)解決。XML命名空間定義了一種將XML中使用的元素和屬性與統(tǒng)一資源定位符(Uniform Resource Locator,URL)引用聯(lián)系起來(lái)對(duì)元素和屬性進(jìn)行定義的方法。 統(tǒng)一資源定位符(URL)是用于完整地描述Internet上網(wǎng)頁(yè)和其他資源的地址的一種標(biāo)識(shí)方法。Internet上的每一個(gè)網(wǎng)頁(yè)都具有一個(gè)唯一的名稱標(biāo)識(shí),通常稱之為URL地址,這種地址可以是本地磁盤,也可以是局域網(wǎng)上的某一臺(tái)計(jì)算機(jī),更多的是Internet上的站點(diǎn)。簡(jiǎn)單地說(shuō),URL就是Web地址,俗稱“網(wǎng)址”。
1.2.2 XMPP的數(shù)據(jù)結(jié)構(gòu)
從結(jié)構(gòu)上看,XMPP有3種數(shù)據(jù):XML流、流認(rèn)證和XML節(jié)。XML流是實(shí)體交換XML元素的容器,以<stream>開始,以</stream>結(jié)束,是通信雙方采用異步方式進(jìn)行數(shù)據(jù)傳輸?shù)臉?biāo)準(zhǔn)方法,在整個(gè)XMPP通信過(guò)程中處于最外層;XML節(jié)是實(shí)體通過(guò)XML流傳輸?shù)慕Y(jié)構(gòu)化信息單元,在XML流中以深度為1的子標(biāo)記開頭,并以深度為1的子標(biāo)記結(jié)束,這些標(biāo)記為<message/>、<presence/>和<iq/>。
XMPP為XML流扮演通用“傳輸層”的角色。XML流中包含傳輸?shù)恼J(rèn)證信息和現(xiàn)場(chǎng)消息,XMPP能使數(shù)據(jù)高效路由至最合適的請(qǐng)求源,并最大限度地簡(jiǎn)化客戶機(jī)上的實(shí)現(xiàn),使跨應(yīng)用實(shí)時(shí)交流信息成為可能。
2 工作過(guò)程
?。?)節(jié)點(diǎn)(如yb、pt)向本地服務(wù)器連接。
?、賆MPP用戶通過(guò)開啟一個(gè)從客戶端到服務(wù)器端的XML流,來(lái)申請(qǐng)一個(gè)在服務(wù)器上的Socket連接。
SEND: <stream:stream
to=′sdpt.com′
xmlns=′jabber:client′
xmlns:stream=′http://etherx.jabber.org/streams′>
?、诜?wù)器通過(guò)開啟一個(gè)從服務(wù)器到客戶端的XML流進(jìn)行回復(fù)。
RECV: <stream:stream
from=′sdpt.com′
id=′180763465′
xmlns=′jabber:client′
xmlns:stream=′http://etherx.jabber.org/streams′>
?。?)節(jié)點(diǎn)向本地服務(wù)器申請(qǐng)登錄。
?、儆脩粼儐?wèn)登錄服務(wù)器時(shí)需提供的信息。
SEND: <iq id=′2′ type=′get′>
<query xmlns=′jabber:iq:auth′>
<username>yb</username>
</query>
</iq>
?、诜?wù)器回應(yīng)用戶,告知用戶登錄所需要的信息。
?、塾脩籼峁┧璧男畔ⅰ?/p>
?、芊?wù)器響應(yīng)一個(gè)空的類型為“result”的iq元素,表明登錄成功。
RECV:<iq id=′3′ type=′result′/>
?、輞b用戶發(fā)送當(dāng)前狀態(tài)給服務(wù)器,表明其在線。
SEND: <presence>
<status>Online</status>
</presence>
?。?)用戶獲得花名冊(cè),好友增加一個(gè)聯(lián)系人(如yb獲知朋友sd在線)。
?。?)用戶間發(fā)送消息(如yb向sd發(fā)送消息)。
用戶發(fā)送一條消息:
SEND: <message to′sd@jabber.org′>
<body>Where are you?</body>
</message>
服務(wù)器會(huì)根據(jù)XMPP用戶的會(huì)話信息加上一個(gè)源地址,這樣接收者收到消息時(shí),消息中已經(jīng)包含了源地址。
?。?)XMPP服務(wù)器根據(jù)目標(biāo)JID中的域名查找、連接到目標(biāo)服務(wù)器并進(jìn)行認(rèn)證(如sdpt.com使用DNS查找jabber.org,連接到j(luò)abber.org服務(wù)器上并進(jìn)行認(rèn)證)。
?。?)XMPP服務(wù)器jabber.org證實(shí)sd連接到該服務(wù)器上,yb被授權(quán)與sd進(jìn)行通信。
?。?)數(shù)據(jù)在yb與sd間流動(dòng)。
?。?)用戶退出,退出時(shí)只需要關(guān)閉<stream>。3 安全機(jī)制
3.1 簡(jiǎn)單認(rèn)證和安全層協(xié)商機(jī)制
簡(jiǎn)單認(rèn)證和安全層(Simple Authentication and Security Layer,SASL)可以為基于連接的協(xié)議加入認(rèn)證機(jī)制,提供KERBEROS_V4、PLAIN和DIGEST-MD5等多種認(rèn)證方法。每種認(rèn)證機(jī)制包含認(rèn)證機(jī)制名、認(rèn)證過(guò)程初始化命令、認(rèn)證控制命令、特定8位碼和解釋器等信息。
在認(rèn)證過(guò)程中,認(rèn)證服務(wù)器完成認(rèn)證、授權(quán)標(biāo)識(shí)傳送、簡(jiǎn)單認(rèn)證和安全層協(xié)商3個(gè)方面的工作。在XMPP中,SASL處理步驟如下(C:客戶端,S:SASL認(rèn)證服務(wù)器):
(1)C、S之間建立連接。(2)S向C提供認(rèn)證機(jī)制列表。(3)C在認(rèn)證機(jī)制列表中選擇一種認(rèn)證機(jī)制。(4)S向C詢問(wèn)授權(quán)信息。(5)C向S提交授權(quán)信息。(6)S向C返回認(rèn)證成功或失敗信息。
3.2 回?fù)苷J(rèn)證
在通信過(guò)程中,2個(gè)XMPP服務(wù)器之間經(jīng)常需要通信,為避免利用服務(wù)器欺騙方式進(jìn)行信息偽造,XMPP 采用了回?fù)苷J(rèn)證機(jī)制?;?fù)苷J(rèn)證依靠DNS技術(shù)完成,利用回?fù)苷J(rèn)證機(jī)制,一個(gè)服務(wù)器可以確認(rèn)與自己建立連接的服務(wù)器是否經(jīng)過(guò)合法授權(quán),回?fù)苷J(rèn)證過(guò)程為:(1)源服務(wù)器和接收服務(wù)器建立連接,并向接收服務(wù)器請(qǐng)求認(rèn)證。接收服務(wù)器回應(yīng),并分配認(rèn)證會(huì)話ID。(2)源服務(wù)器向接收服務(wù)器發(fā)送認(rèn)證密鑰。(3)接收服務(wù)器與認(rèn)證服務(wù)器建立連接。認(rèn)證服務(wù)器同時(shí)為該認(rèn)證會(huì)話分配一個(gè)驗(yàn)證會(huì)話ID。(4)接收服務(wù)器把源服務(wù)器提交來(lái)的密鑰和驗(yàn)證會(huì)話ID 發(fā)送給認(rèn)證服務(wù)器,請(qǐng)求驗(yàn)證。(5)認(rèn)證服務(wù)器驗(yàn)證密鑰,并給接收服務(wù)器返回認(rèn)證結(jié)果。(6)接收服務(wù)器給源服務(wù)器返回認(rèn)證結(jié)果。
3.3 加 密
雖然SASL提供了先進(jìn)的認(rèn)證機(jī)制,通信雙方必須經(jīng)過(guò)特定的授權(quán)認(rèn)證才能進(jìn)行正常通信,但是登錄信息一般都是密碼和用戶名等重要信息,它們大多采用明文方式傳送,因此很容易被竊聽。為解決該問(wèn)題,XMPP采用基于傳輸層安全協(xié)議的“STARTTLS”擴(kuò)展來(lái)為通信雙方提供機(jī)密性和數(shù)據(jù)完整性服務(wù)。TLS 協(xié)議包括兩個(gè)協(xié)議組―― TLS 記錄協(xié)議和 TLS 握手協(xié)議――每組具有很多不同格式的信息。TLS 記錄協(xié)議是一種分層協(xié)議。每一層中的信息可能包含長(zhǎng)度、描述和內(nèi)容等字段。記錄協(xié)議支持信息傳輸、將數(shù)據(jù)分段到可處理塊、壓縮數(shù)據(jù)、應(yīng)用 MAC 、加密以及傳輸結(jié)果等。對(duì)接收到的數(shù)據(jù)進(jìn)行解密、校驗(yàn)、解壓縮、重組等,然后將它們傳送到高層客戶機(jī)。TLS 連接狀態(tài)指的是TLS 記錄協(xié)議的操作環(huán)境。它規(guī)定了壓縮算法、加密算法和 MAC 算法。TLS 記錄層從高層接收任意大小無(wú)空塊的連續(xù)數(shù)據(jù)。密鑰計(jì)算:記錄協(xié)議通過(guò)算法從握手協(xié)議提供的安全參數(shù)中產(chǎn)生密鑰、 IV 和 MAC 密鑰。TLS 握手協(xié)議由三個(gè)子協(xié)議組構(gòu)成,允許對(duì)等雙方在記錄層的安全參數(shù)上達(dá)成一致、自我認(rèn)證、例示協(xié)商安全參數(shù)、互相報(bào)告出錯(cuò)條件。
TLS協(xié)議框架主要有2個(gè)層次的協(xié)議:TLS握手協(xié)議和TLS記錄協(xié)議。TLS握手協(xié)議用來(lái)讓服務(wù)器與客戶在傳輸應(yīng)用層數(shù)據(jù)之前交換TLS協(xié)議版本信息、協(xié)商加密算法、進(jìn)行(相互)身份認(rèn)證并交換密鑰。TLS記錄協(xié)議用來(lái)將應(yīng)用層提供的信息進(jìn)行分組、壓縮、數(shù)據(jù)完整性檢查和加密。數(shù)據(jù)完整性檢查通過(guò)比較傳輸前后使用安全散列函數(shù)(如SHA和MD5 等)計(jì)算出來(lái)的數(shù)據(jù)的MAC值是否一致來(lái)完成。數(shù)據(jù)加密采用對(duì)稱密碼算法(如R4和DES等)。對(duì)數(shù)據(jù)進(jìn)行完整性檢查和加密的密鑰由TLS握手協(xié)議來(lái)協(xié)商。
XMPP中采用的STARTTLS擴(kuò)展處理流程如下(C:客戶端,S:TLS服務(wù)器):
?。?)C、S之間建立XML流會(huì)話連接。
(2)S 向C 發(fā)送STARTTLS擴(kuò)展服務(wù)需求及支持的其他認(rèn)證機(jī)制列表,代碼實(shí)例如下:
<stream:features>
<starttls xmlns=′urn:ietf:params:xml:ns:xmpp-tls′>
<required/>
</starttls>
<mechanisms xmlns=′urn:ietf:params:xml:ns:xmppsasl′>
<mechanism>DIGEST-MD5</mechanism>
<mechanism>PLAIN</mechanism>
</mechanisms>
</stream:features>
?。?)C發(fā)送STARTTLS命令給S。
?。?)C、S中TLS握手協(xié)議開始協(xié)商相關(guān)加密算法及密鑰。
(5)若TLS握手協(xié)議協(xié)商成功,則關(guān)閉當(dāng)前XML流會(huì)話,C發(fā)起一個(gè)新的XML流會(huì)話,所有傳送的信息均被TLS記錄協(xié)議加密。TLS握手協(xié)議協(xié)商不成功則發(fā)出警告信息。
?。?)S向C回復(fù)新XML流會(huì)話。
4 客戶端程序設(shè)計(jì)中的關(guān)鍵問(wèn)題
由于網(wǎng)絡(luò)中已存在大量的XMPP服務(wù)器,在一般的應(yīng)用開發(fā)中,只要設(shè)計(jì)自定功能的客戶端程序即可,并可以選用Smack庫(kù)來(lái)加速開發(fā)。
?。?)創(chuàng)建一個(gè)XMPP連接。因?yàn)閄MPP使用TCP協(xié)議,所以首先必須創(chuàng)建一個(gè)網(wǎng)絡(luò)連接,XMPPConnection就是Smack庫(kù)用來(lái)創(chuàng)建與XMPP服務(wù)器連接的類,創(chuàng)建一個(gè)XMPP連接的代碼如下:
XMPPConnection connection=new XMPPConnection(″jab-
ber.org″);
如要?jiǎng)?chuàng)建加密連接,可以使用SSLXMPPConnection類:
XMPPConnection connection=new SSLXMPPConnection(″jabber.org″);
?。?)登錄。TCP連接創(chuàng)建后,需要使用用戶名和密碼登錄到XMPP服務(wù)器,登錄程序可以使用XMPPConnection.login(String username,String password)方法。登錄后就可以和其他人聊天。
connection.login(″yb″,″password″);//connection為已創(chuàng)建的XMPP連接,下同
connection.createChat(″yb@sdpt.com″)。sendMessage
?。?Prime;Hello!″);
(3)操作名冊(cè)。每個(gè)用戶都包括:一個(gè)XMPP地址(如mailto:%E2%80%9Cyb@sdpt.com”)、名稱或昵稱(如″yb″),及其所屬列表(如好友、同事等)。名冊(cè)能夠跟蹤好友或某用戶組是否在線及其狀態(tài)信息,登錄后,可以使用Roster類來(lái)取得好友或某用戶組的狀態(tài),代碼如下:
Roster roster=con.getRoster( );
for (Iterator i=roster.getEntries( );i.hasNext( ); ) {
System.out.println(i.next( ));}
名冊(cè)信息通常是隨時(shí)變化的,可能需要增加或刪除。要監(jiān)聽名單及其在線狀態(tài)的改變,可以使用RosterListener。
?。?)發(fā)送和接收消息。發(fā)送接收消息可以使用Chat和GroupChat類。下面介紹如何使用Chat發(fā)送文本消息,GroupChat的使用方法類似。
Chat newChat=connection.createChat(″yb@sdpt.com″);//創(chuàng)建新Chat
newChat.sendMessage(″Hello!″);//發(fā)送消息″Hello!″
利用Chat.sendMessage( )方法可以方便地創(chuàng)建一個(gè)消息對(duì)象,它的參數(shù)就是消息內(nèi)容,執(zhí)行后消息會(huì)發(fā)送出去。
Chat newChat=connection.createChat(″yb@sdpt.com″);
newMessage.setBody(″Hi, I′m waiting for you.″);
while (true) {
Message message=newChat.nextMessage( );//等待對(duì)方發(fā)送消息
newChat.sendMessage(message.getBody());//把對(duì)方
}//發(fā)送來(lái)的消息發(fā)回去
(5)修改狀態(tài)。要修改狀態(tài)可以用presence.Type.UNAV-ILABLE作為參數(shù)創(chuàng)建一個(gè)presence,狀態(tài)將改變?yōu)椴辉诰€狀態(tài)。
Presence presence=new Presence(Presence.Type.UNAVAILABLE);
presence.setStatus(″Gone skating″);
5 結(jié)束語(yǔ)
目前,全球有20萬(wàn)個(gè)即時(shí)通信平臺(tái)支持XMPP,有1 000萬(wàn)人在使用。簡(jiǎn)單的接口、開放的協(xié)議、互聯(lián)的架構(gòu)、權(quán)威的標(biāo)準(zhǔn)再加上堅(jiān)實(shí)的用戶基礎(chǔ)是XMPP的優(yōu)勢(shì)。