xmpp 協議的這個名稱就來自于它的訊息包格式借鑒了 xml 的格式,但并不是我們常規編程中的那種完整的 xml 資訊包,因此就不能用普通的 xml 解碼庫來操作這些訊息,一般的情況下是需要另外開發的,而實際的開發中通常使用第三方庫,但就目前的第三庫現狀來說,可以說是不怎么好用,所以我們來看看如何手工自己進行訊息的解碼,
首先第一句話就是一個坑,以我們前面提到的從服務器中收到的第一句為例:
<?xml version='1.0'?> <stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' from='xumatomacbook-pro.local' id='675c6847-c13d-4710-9844-d9339e4df087' version='1.0' xml:lang='en'>
乍一看上去,你會以為第一句話是 “<?xml version='1.0'?>”,好我們開始解碼這句話吧,答案是 NO !這句話是可有可無的,所以我們解碼的第一個作業就是判斷起始句是 xml 部分還是后面的 stream 部分,
實際上我們的做法是根本不解碼!讀者一定瞠目結舌不敢相信,對的,實際上我們對 xmpp 協議進行操作根本不需要 xml 解碼器,只使用幾個字串查找和截取函式就可以了!
能夠這樣做的根本原因就在于 xmpp 協議并不是完整的 xml 包,實際上它和我們前面文章中的 SMTP/POP3 協議一樣是服務器與客戶端的一問一答式的問答包(當然也還不完全是,我們后面會說到),只是借助了 xml 的封裝形式而已,
在 xmpp 協議中,服務器發出第一句話之后就馬上要發送登錄方法說明包,即
<stream:features><mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><mechanism>PLAIN</mechanism></mechanisms></stream:features>
類似于這樣的格式,實際上我們在操作中直接將它們當做一個包處理就行了,就是說可以直接忽略掉第一個包,不管它有沒有“<?xml version='1.0'?>”,在編程上就是一直讀取服務器 socket 中的內容,我們將當前讀取到而沒有處理的內容當做一個字串(而不是 xml 流),給它一個變數名為gRecvBuf,
然后每當 socket 介面上有資料來到事件時就去檢測gRecvBuf 中是否已經包含了字串“mechanism”,如果有,就說明已經收完了第一個包,服務器告訴我們可以發送登錄資訊了,偽碼如下:
if FindStr('mechanism', gRecvBuf) {
[做登錄的各種動作]
}
但這樣其實也不對!因為,含有“mechanism”并不能說明整個登錄包結束了,還記得我們前面學習 SMTP/POP3 是如何判斷一個包什么時候結束了嗎?一般情況下是判斷是否有“\r\n”,xmpp 協議其實也是判斷是否有某個結束符字串,只不過這個結束符號不是固定的,而是針對不同的命令而不同而已!這就是 xmpp 協議操作中最關鍵的部分,實際上不光 xmpp 包括 SMTP/POP3 以及我們還計劃要解說的 http 協議的操作中最關鍵的就是要找到一個包結束的位置和方法,解決了這個問題就可以說成功了一大半,
而對于我們現在的這個包,它的結束符號是 “</mechanism>”,這里就要涉及到 xml 格式的知識了,如果一個 xml 節點中還有子節點的話,它必須包括一個 </[節點名]> 這樣的尾部,所以我們直接利用這一點,在gRecvBuf 中查找到這個字串就是它的包尾了,
了解 xml 格式的讀者可能就會提問說,如果mechanism 節點里還有mechanism 子節點,這個方法就不行了,沒錯,但是剛好 xmpp 協議中是沒有這種情況的,所以我們可以放心地使用這種方式,其實就算有這種情況,我們再做進一步處理即可,只是根據 xmpp 協議的特點,沒有必要那樣做,所以實際上正確的操作偽碼應該是:
if FindStr('</mechanism>', gRecvBuf) {
[做登錄的各種動作]
}
這其中要注意的是,查找字串函式應該是忽略大小寫的,因為節點名是有可能含有大小寫混用的情況的,出于兼容性的考慮,能忽略大小寫是最好的,
這是非常重要的一個章節,建議大家仔細反復研究一下,雖然內容不多,但這是我們整個 xmpp 協議訊息包處理的中心思想,非常的關鍵,也非常的簡潔有效,
--------------------------------------------------
著作權宣告:
本系列文章已授權百家號 "clq的程式員學前班" . 文章編排上略有差異.
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/111800.html
標籤:其他
