發布報文的知識點並不難,只是多。看過前面幾章的讀者們應該或多或少都認識服務質量QOS。發布報文跟他的聯系最緊的。我們也清楚訂閱報文里面雖然也有用到QOS,但是他卻沒有更進一步的聯系。往下看就知道是什么一會事了。
服務質量QOS
不管是訂閱報文還是發布報文都會遇到一個問題——報文流失的問題。所以才會有了服務質量這一說法(個人看法)。什么意思呢?就是用來處理流失的問題。即然報文在發送的過程中可能存在流失的問題。那么最直接的決解方案就是重新發送,不就行了嗎。所以服務質量事實就是在表示報文要分送幾次。QOS有三個值。分別表示着三種不同的處理報文方式。相應的值如下
QOS 0:最多分發一次。即是可以零次或是一次。不過筆者認零次的情況大多數是不可能存在的。一次到很常見。
QOS 1:至少分發一次。
QOS 2:只分發一次。
筆者在看MQTT協議文檔的時候,對於QOS的分發一直有一個小問題。筆者以為是指客戶端到客戶端的分發。不過看了幾遍覺得他是指客戶端到服務端的分發。那么為什么筆者會認為是客戶端到客戶端的分發呢?主要是筆者認為QOS是指報文到客戶端的次數。比如QOS 1說明分送到每一個符合客戶端的報文至少一次。所以才會有至少分送一次的說法。原來一開始筆者理解錯了。所以請記住這里服務質量QOS是指客戶端與服務端的分發。所謂的分發- 次,至少一次,更不是指報文到客戶端的次數。
如果分發是客戶端到服務端的話。假設服務端收到了QOS 1的報文。那么服務端就會回發一個響應表示收到,QOS 1的處理就這樣子結束了。而服務端還要把這個報文發送到別的符合的客戶端。這個時候還是存在的報文流失的問題。你們也清楚網絡有時候就是這樣子。當然這個可能筆者多慮了。但是服務質量QOS就是把相關的報文不停的重發。那么對於重數的次數MQTT肯定不可能不做一些記錄。所以固定報頭的DUP作用就出來了。重發一次就把DUP加1。下面筆者會細說。
服務質量QOS 0 筆者喜歡用一詞來形客。管殺不管埋。發出去之后。收不收的到不管了。當然筆者說的有一點過頭了。這里是指客戶端向服務端發送發布報文,只要服務端接收到了。那么客戶端就在也不管了。
服務質量QOS 1的要求是至少分發一次。如果失敗的話就一直重復分發。筆者先把流程寫出來。然后加一張圖來加深理解。
1)客戶端向服務端發起一個發布報文。如果服務端沒有接到。請你繼續起發不用客氣。
2)服務端收到一個來看客戶端的發布報文。查看一下原來是服務質量QOS為1的報文。服務端就必須回發一個叫發布確認(PUBACK)的報文。而這個時候客戶端也在等待着服務端的回應(好了故事就從這里開始了)。
3)客戶端等了一段時間就是沒有接到來自服務端的回應,沒有辦法客戶端只能認為失敗了。在重發一次吧。這個時候客戶端就必須把固定報頭里面的DUP加1了。但是服務端事實上沒有問題,並且開始給符合主題的客戶端們發分信息了。只是可能這一段時間正在處理一些事情,回應慢了。
4)客戶端終於接收到了回應(PUBACK)。結束了。
注意:圖片中的紅線就是一個重發的環。
從上面的流程我們就可以看出來一個問題,服務端有可能收到多次的發布報文。那么當服務端在次接收到DUP大於0的報文,不管他,當前普通的報文一樣了處理。同樣子也要給客戶端一個回應,不然他又要重發了。那么這就意味着服務端要處理相同的發布報文問題。可惜文檔里面要求當作正常的報文來處理就行了。即是不管是不是重發的報文,只要接到報文並且他的QOS大於0,那么給對應的客戶端一個回應。同時給符合主題的客戶端們分發報文。顯然客戶端們會接收到多個相同的信息了。
服務質量QOS 2表示只分發一次。 筆者在看文檔MQTT 3.1里面的QOS2 處理時候,有一點不理解。后來在去看一下MQTT 3.1.1果然寫的清楚一點了。不然筆者以為跟服務質量QOS 1沒有什么區別。讓我們看一下他是什么處理才只分一次呢?
1)客戶端向服務端發起一個發布報文。如果服務端沒有接到。請你繼續起發不用客氣。
2)服務端收到一個來看客戶端的發布報文。查看一下原來是服務質量QOS為2的報文。服務端處理相關操作之后,就回應一個叫PUBREC 的報文。如果是服務質量QOS 1的話,這個時候會給符合的客戶端們發送信息。那么服務質量QOS 2這邊要不要這個時候給符合主題的客戶端們發送信息呢?當然這一點檔文也沒有特別指出來。所以筆者認為應該是可以的。同時服務端還要等待來自客戶端的一個叫PUBREL的報文呢?
3)客戶端在一段時間之后,如果沒有收到相關回應的話,重發一次,同時DUP加1。直到接收到回應(PUBREC)。
4)當前客戶端接收到了來自服務端的回應(PUBREC)。客戶端就必須在回頭跟服務端說一聲:“我收到你的回應了”。因為服務端一直在等客戶端的回應,即是PUBREL報文。如果客戶端一直不給服務端回發一個回應,表示客戶端已經收到回應。服務端會一直重發PUBREC。這個時候DUP有沒有加1。文檔里面沒有說明。所以應該是不需要。直到服務端接收到客戶端的回應(PUBREL)。在筆者心里面這里才是給符合主題的客戶端們發送信息的時候。
5)客戶端在給服務端發送PUBREL報文,說明我收到了你的回應了。同時客戶端又在等待服務端的另一個回應。告訴客戶端動作結束了。即是PUBCOMP報文。
6)客戶端收到來自服務端的PUBCOMP報文響應。結束了。
注意:圖片中的紅線就是一個重發的環。
理論上來講服務質量QOS 2的安全等級絕對高於服務質量QOS 1。關是步棸QOS 2就比QOS1多了二步。而且這二步都是一個重發的環。圖片中我們可以看到。可是如果細想一下,筆者心里面有一點不理解。所謂的至少分一次,只分發一次好像並沒有體現出來。如QOS 2里面客戶端沒有接到PUBREC的報文時候,不是還是要重發一下發布報文。那么所以只分發一次。理解上就有一點怪怪的。筆者也想過可能QOS 2會根據消息ID特別處理報文,讓同一個報文只處理一次。不然的話,不是還是會出現QOS 1那樣子客戶端們可能會收到重復的信息。可是筆者在MQTT 文檔里面沒有找到。這一點讀者們自行去查看吧。
不管是QOS 1還是QOS 2。最后都要給符合主題的客戶端發送信息。那么關鍵點是在什么時候發送。雖然文檔里面有指出可以在PUBACK或是PUBREC之后就可以給符合主題的客戶端發送信息。總之筆者沒有找到特別指出的地方。所以大部分都是網絡說的。QOS 1在PUBACK發出之后就可以發送給客戶端信息。QOS 2在服務端接受PUBREL之后發送給客戶端信息。當然讀者們也可以自行選擇吧。
發布報文結構
發布報文的格式比較單簡。即然是發布報文那么主題和發布的內容是一定少了的。所以相對於別他報文來講,發布報文對固定報頭,可變報頭,還有有效載荷都有需要。固定報頭筆者就不用多講了。把官方的列表拿過來大家自己看。就是那幾個常用的信息。如下
看列表就是他的固定報頭的二進制是00110000或是00110010或是00110100。分別對應QOS 0,QOS 1,QOS2。
可變報頭里面存放了倆個信息對服務端來講很重要。一個是主題,一個是消息ID。除了這倆個沒有別的了。如下
官方的列表第一次看時候是有一點看不懂。特別是byte1,byte2是什么。如果看不懂他也沒有事。你只要明白這些是組成元素就可以了。如上面列表的主題是“a/b”。有三個元素組成的。后面就是每一個元素對應的二進制。而LSB和MSB前面講過了。
有效載荷就是存放就是發布的內容了。略過。
這一部分的代碼筆者就不寫了。因為筆者比較賴。只要上章讀者們有去實現把相關訂閱的主題保留住的話,那么發布報文的時候,只要從保留的主題中找到符合的。然后過通主題的信息找到對應的客戶端連接。在發送信息就行了。但是一定要記得服務質量的要求。筆者這里只分析包的結構。如下
服務質量QOS 0的發布報文包
圖片上筆者已經標出來相關的內容。分別為不同的顏色。我們知道服務質量QOS 0是沒有回應的。所以只是單向的發送。比較簡單。但是有一點要記得他好像沒有消息ID。
服務質量QOS 1的發布報文包
我們可以看到跟QOS 0沒有什么區別。主要是有了消息ID。但很重要。
服務質量QOS 1的發布報文確定(PUBACK)包
我們發現他沒有有效載荷。除了固定報頭之外,就是可變報頭,同時只有一個消息ID。而且跟上面的發布報文的消息ID是相同的。
服務質量QOS 2的發布報文包
服務質量QOS 2的發布確定包(PUBREC)
相同的消息ID,沒有有效載荷
服務質量QOS 2的發布確定包(PUBREL)
相同的消息ID,沒有有效載荷
服務質量QOS 2的發布確定包(PUBCOMP)
相同的消息ID,沒有有效載荷