首頁 > 軟體

xmppmini 項目詳解:一步一步從原理跟我學實用 xmpp 技術開發 3.第一句訊息的解碼及解碼的原理

2020-09-23 12:30:11

    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 是如何判斷一個包什麼時候結束了嗎?一般情況下是判斷是否有“rn”,xmpp 協議其實也是判斷是否有某個結束符字元串,只不過這個結束符號不是固定的,而是針對不同的命令而不同而已!這就是 xmpp 協議操作中最關鍵的部分。實際上不光 xmpp 包括 SMTP/POP3 以及我們還計劃要解說的 http 協議的操作中最關鍵的就是要找到一個包結束的位置和方法,解決了這個問題就可以說成功了一大半。

而對於我們現在的這個包,它的結束符號是 “</mechanism>”,這裡就要涉及到 xml 格式的知識了,如果一個 xml 節點中還有子節點的話,它必須包括一個 </[節點名]> 這樣的尾部。所以我們直接利用這一點,在gRecvBuf 中查詢到這個字元串就是它的包尾了。

瞭解 xml 格式的讀者可能就會提問說,如果mechanism 節點裡還有mechanism 子節點,這個方法就不行了。沒錯,但是剛好 xmpp 協議中是沒有這種情況的,所以我們可以放心地使用這種方式。其實就算有這種情況,我們再做進一步處理即可,只是根據 xmpp 協議的特點,沒有必要那樣做。所以實際上正確的操作偽碼應該是:

 

if FindStr('</mechanism>', gRecvBuf) {

  [做登入的各種動作]

}

 

這其中要注意的是,查詢字元串函數應該是忽略大小寫的。因為節點名是有可能含有大小寫混用的情況的,出於相容性的考慮,能忽略大小寫是最好的。

這是非常重要的一個章節,建議大家仔細反覆研究一下,雖然內容不多,但這是我們整個 xmpp 協議訊息包處理的中心思想,非常的關鍵,也非常的簡潔有效。

--------------------------------------------------

版權聲明:

本系列文章已授權百家號 "clq的程式設計師學前班" . 文章編排上略有差異.


IT145.com E-mail:sddin#qq.com