文章**於
我們已經把相關的連線報文搞定了。筆者想來想去還是決定先講解一下訂閱報文(subscribe )。如果傳統的通訊方式是客戶端和服務端之間一般就直接傳輸資訊。但是mqtt的通訊方式是通過釋出/訂閱的方式進行的。筆者不知道他是否跟設計模式中的釋出訂閱模式有沒有關係。可是他們思想卻有一點相似之處。
注意:釋出者也是客戶端。訂閱者也是客戶端
主題(topic )
如果主題只是一個字串值的話,那麼顯然會比較單調。這樣子功能也顯得比較無力。所以在主題上面就了所謂的分隔符和萬用字元的說法(個人想法)。分隔符的意思就是讓主題可以分層次。就好如說主題“體育講壇/籃球/nba”。看到這樣子的主題,請問一下你還有什麼不明白的話。是不是感覺很有層次感。剩下只有一個問題?如果我們訂閱了主題“體育講壇/籃球/nba”,並向主題“體育講壇/籃球”釋出一個資訊。那麼已經訂閱主題“體育講壇/籃球/nba”的客戶端們是不是可以接受到資訊呢?反過來講如果我們訂閱了主題“體育講壇/籃球”,向主題“體育講壇/籃球/nba”發資訊,客戶端們是否又能接受資訊呢?
筆者就以hivemq作伺服器來做一下上面的小實驗。如下
客驗結果顯然是失敗的——訂閱主題“體育講壇/籃球/nba”的客戶端根本收不到來自主題“體育講壇/籃球“的釋出資訊。說明分隔符就是用於主題名的分層次。沒有別的意思。
通過上面的實驗我們知道如果想要收到nba就是必須訂閱主題“體育講壇/籃球/nba”。可是總是有一些人只要是籃球的新聞有喜歡。怎麼辦。萬用字元的功能就出來了。萬用字元有倆種——"+"和“#”。+為單層的萬用字元。表示當前這一層的全都合非。這樣子以上面的說到的例子來做實驗。我們訂閱一個主題為“體育講壇/籃球/+”。按照理解的意思就是只要是在“體育講壇/籃球”的資訊都是我們想要的。結果如下
我們可以看到筆者在“體育講壇/籃球/nba”和“體育講壇/籃球/abc”各發布了資訊。結果他都能收到。那麼如果我們對主題“體育講壇/籃球”或是主題“體育講壇/籃球/nba/福州專場”釋出資訊呢?筆者試過了很可惜都不行。
實驗的結果很終滿足了。
對於主題,在文件中有一個要求——主題不能以 ”#“ "+" "$" 為開頭。對於”#“ ” +“的話,大家都好理解。那麼”$“又是什麼鬼。在文件我們可以看到這樣子的字元"$sys"。事實上他們是想說”$“開頭的主題一般用於系統內部的一些主題。你們可以去找一些第三方的mqtt伺服器。都會有很多以”$“開頭的主題。
subscribe報文
通過上面的介紹。筆者想你們一定對mqtt通訊方式有了一定的概念。而本章的訂閱報文就是用於告訴伺服器我想要什麼的主題了。通過前面幾章的瞭解。我們知道報文的固定報頭是少了的。筆者就以mqtt 3.1.1來介紹吧。如下
subscribe報文的int值是8。所以對應的二進位制為1000。後面的dup qos retain對應是0010。其中qos是必須是01。對訂閱者來講,他一定希望自己的訂閱是成功的。所以訂閱報文的qos是01就相當好理解了。如果不理解qos是什麼的話,請看一下前面幾章。
訂閱報文也有可變報頭,可變報頭只有一個訊息id。訊息id是從客端端開始分配的。筆者為什麼樣子認為呢?主要是看到客戶端在釋出資訊的時候就要求訊息id。所以筆者才會覺得訊息id在客戶端進行分配的。當然也不是什麼報文都會訊息id的。但是有訊息id一般qos大於0。
訂閱報文的有效載荷裡面存在了相關的訂閱訂題列表。前面說過可以支援一個客戶端多個訂閱。列表裡面每有一主題項只有倆個值。一個表示主題名,一個表示服務質量要求(requested qos)。這裡的服務質量要求(requested qos)和 固定報頭的服務質量的值是一樣子。但是用意卻是不一樣子。這裡是指這個訂閱者接收這主題的服務質量最大等級。舉個列子吧。筆者訂閱了一個主題主題“體育講壇/籃球/nba”,同時他的服務質量要求(requested qos)的值為1。這個時候有一個釋出者在這個主題上釋出一個服務質qos為2。筆者還是可以收到這個釋出者發來的資訊。只是資訊的服務質量qos卻變為1了。要明白qos(1)和qos(2)的執行行為是不樣子的。這個後面章節會講到。當然如果釋出者在這個主題上釋出一個服務質qos為0。這就沒有什麼區別了。如下
對於有效載荷筆者這裡就不多講解了。也沒有什麼可說的。看文件的就夠了如下。
巨集觀上:
微觀上:
列表出我們可以看他訂閱了倆個主題。一個主題”a/b“,一個主題”c/b“。上面列出大概的(巨集觀上)和比較細的(微觀上)。如果看不懂也沒有關係。筆者接下來會用**來抓一包看看。相信在對照一下就明白列表出畫的是什麼。
現在讓我們好好想想當伺服器接收到來自客戶端的訂閱報文的時候要做些什麼樣子的反應呢?首先我們要明白如果服務端接收到一個訂閱報文,第一步想到一定是檢視訂閱報文的格式是不是正確的。相關的主題名是不是為空的。主題名的寫法是不是非法。這些一定離不開。當然對應的一些共有的驗證筆者就不說了。一切沒有問題的情況下,伺服器會去看一下當前訂閱者前面有沒有訂閱過相同的主題。如果有就替換當前的。如果沒有就建立一下新的。然後伺服器在根據當前主題查詢一下符合保留的資訊。如果有,就傳送給當前的訂閱者。然後傳送一個訂閱報文確定(suback )。當然這前後沒有規定。先傳送一個訂閱報文確定(suback ),在處理保留的資訊也是可以的。
注意:在傳送符合保留的資訊就要對qos進行處理。上面筆者也講過了。
suback 報文
當服務端處理subscribe報文的時候,都會生成一個suback 報文來回應訂閱者。筆者這裡不想對他太過的講解。他的內容也很簡單。如下
對於suback 報文的可變報頭裡面也只有一個訊息id。而且跟subscribe報文的訊息id是一樣子的。有效載何的內容存放是訂閱主題的服務質量要求(requested qos)。筆者在mqtt 3.1 文件時面可以看到有多個主題的列子。可是在mqtt 3.1.1裡面卻沒有。那麼筆者就把mqtt 3.1.1的放在下里吧。讀者們可以自行檢視。
上面列表裡面顯示返回碼,事實上是主題相關的服務質量要求(requested qos)。所以就可以知道他可以會返回四個值。如下
qos 0:0x00
qos 1:0x01
qos2 :0x02
failure :0x80
理解MQTT主題
mqtt主題是一種定址方式,它允許mqtt客戶端共享資訊。mqtt主題的結構類似於檔案系統中的資料夾和檔案,使用正斜槓 作為分隔符。使用這個系統,您可以建立一個使用者友好的和自描述的命名結構,由您自己選擇。主題名稱 除 sys主題外,沒有預設主題或標準主題結構。預設情況下,除了 sys主題外,在伺服...