發佈報文的知識點並不難,只是多。看過前面幾章的讀者們應該或多或少都認識服務質量QOS。發佈報文跟他的聯繫最緊的。咱們也清楚訂閱報文裏面雖然也有用到QOS,可是他卻沒有更進一步的聯繫。往下看就知道是什麼一會事了。安全
服務質量QOS網絡
不論是訂閱報文仍是發佈報文都會遇到一個問題——報文流失的問題。因此纔會有了服務質量這一說法(我的見解)。什麼意思呢?就是用來處理流失的問題。即然報文在發送的過程當中可能存在流失的問題。那麼最直接的決解方案就是從新發送,不就好了嗎。因此服務質量事實就是在表示報文要分送幾回。QOS有三個值。分別表示着三種不一樣的處理報文方式。相應的值以下spa
QOS 0:最多分發一次。便是能夠零次或是一次。不過筆者認零次的狀況大多數是不可能存在的。一次到很常見。3d
QOS 1:至少分發一次。blog
QOS 2:只分發一次。圖片
筆者在看MQTT協議文檔的時候,對於QOS的分發一直有一個小問題。筆者覺得是指客戶端到客戶端的分發。不過看了幾遍以爲他是指客戶端到服務端的分發。那麼爲何筆者會認爲是客戶端到客戶端的分發呢?主要是筆者認爲QOS是指報文到客戶端的次數。好比QOS 1說明分送到每個符合客戶端的報文至少一次。因此纔會有至少分送一次的說法。原來一開始筆者理解錯了。因此請記住這裏服務質量QOS是指客戶端與服務端的分發。所謂的分發- 次,至少一次,更不是指報文到客戶端的次數。文檔
若是分發是客戶端到服務端的話。假設服務端收到了QOS 1的報文。那麼服務端就會回發一個響應表示收到,QOS 1的處理就這樣子結束了。而服務端還要把這個報文發送到別的符合的客戶端。這個時候仍是存在的報文流失的問題。大家也清楚網絡有時候就是這樣子。固然這個可能筆者多慮了。可是服務質量QOS就是把相關的報文不停的重發。那麼對於重數的次數MQTT確定不可能不作一些記錄。因此固定報頭的DUP做用就出來了。重發一次就把DUP加1。下面筆者會細說。二進制
服務質量QOS 0 筆者喜歡用一詞來形客。管殺無論埋。發出去以後。收不收的到無論了。固然筆者說的有一點過頭了。這裏是指客戶端向服務端發送發佈報文,只要服務端接收到了。那麼客戶端就在也無論了。im
服務質量QOS 1的要求是至少分發一次。若是失敗的話就一直重複分發。筆者先把流程寫出來。而後加一張圖來加深理解。d3
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,沒有有效載荷