MQTT協議(二)——控制報文之連接服務端報文(CONNECT)與確認連接請求(CONNACK)


一、CONNECT – 連接服務端

客戶端到服務端的網絡連接建立后,客戶端發送給服務端的第一個報文必須是CONNECT報文。

在一個網絡連接上,客戶端只能發送一次CONNECT報文。服務端必須將客戶端發送的第二個CONNECT報文當作協議違規處理並斷開客戶端的連接 。

有效載荷包含一個或多個編碼的字段。包括客戶端的唯一標識符,Will主題,Will消息,用戶名和密碼。

除了客戶端標識之外,其它的字段都是可選的,基於標志位來決定可變報頭中是否需要包含這些字段。

1.固定頭

固定頭沒啥可說的的,報文類型是1.

2.可變頭

可變頭一個完整報文如下:

 

--1~6個字節為協議名

MQTT協議名是預先規定好的,這個后續不會變。

--第7個字節為協議級別

其實就是mqtt協議的修訂版本。對於3.1.1版協議,協議級別字段的值是4(0x04)。

如果發現不支持的協議級別,服務端必須給發送一個返回碼為0x01(不支持的協議級別)的CONNACK報文響應CONNECT報文,然后斷開客戶端的連接。

--第8個字節為連接標志

連接標志字節包含一些用於指定MQTT連接行為的參數。它還指出有效載荷中的字段是否存在。有效荷載里有啥全看這個字節的8位字符是0還是1了。

  |--第0位:服務端必須驗證CONNECT控制報文的保留標志位(第0位)是否為0,如果不為0必須斷開客戶端連接。

  |--第1位:清理會話 Clean Session

      這個二進制位指定了會話狀態的處理方式。客戶端和服務端可以保存會話狀態,以支持跨網絡連接的可靠消息傳輸。這個標志位用於控制會話狀態的生存時間。

        這個值是0:服務端可以根據報文里的客戶端標識符,來找之前這個客戶端有沒有連過,連過的話就恢復之前的會話狀態,沒有的話就新建一個會話。

        就算是這個連接斷開了,會話也要保存在服務端,針對這個客戶端訂閱的消息,會保存為會話的一部分,在這個客戶端重新連接后,把這些

        消息再推送給這個客戶端。

        這個值是1:服務端丟棄之前所有的和這個客戶端建立的會話,並開始一個新的會話,新的會話僅持續和網絡連接同樣長的時間。

        與這個會話關聯的狀態數據不能被任何之后的會話重用。

        為了確保在發生故障時狀態的一致性,客戶端應該使用會話狀態標志1重復請求連接,直到連接成功。

        一般來說,客戶端連接時總是將清理會話標志設置為0或1,並且不交替使用兩種值。這個選擇取決於具體的應用。

        清理會話標志設置為1的客戶端不會收到舊的應用消息,而且在每次連接成功后都需要重新訂閱任何相關的主題。清理會話標志設置為0的客戶端會收到所有在它連接斷開期間發布的QoS 1和QoS 2級別的消息。

           因此,要確保不丟失連接斷開期間的消息,需要使用QoS 1或 QoS 2級別,同時將清理會話標志設置為0。

        清理會話標志0的客戶端連接時,它請求服務端在連接斷開后保留它的MQTT會話狀態。如果打算在之后的某個時間點重連到這個服務端,客戶端連接應該只使用清理會話標志0。

        當客戶端決定之后不再使用這個會話時,應該將清理會話標志設置為1最后再連接一次,然后斷開連接。

  |--第2位:遺囑標志 Will Flag

      遺囑比較有用,比如說你手機app訂閱了你家掃地機器人的在線狀態topic,這個在線狀態掃地機器人可以通過遺囑來實現,一旦它斷開了與mqttbroker連接,mqttboker就可以發送機器人在連接時就設置好的遺囑,通知手機機器人掉線了。

      遺囑標志(Will Flag)被設置為1,表示如果連接請求被接受了,遺囑(Will Message)消息必須被存儲在服務端並且與這個網絡連接關聯。也就是確認使用遺囑。

      之后網絡連接關閉時,服務端必須發布這個遺囑消息,除非服務端收到DISCONNECT報文時刪除了這個遺囑消息。

      如果決定啟用遺囑,那么連接標志中的Will QoS和Will Retain字段會被服務端用到,同時有效載荷中必須包含Will Topic和Will Message字段。因為你得組織服務端遺囑的publish的報文。

      如果被設置成了0,連接標志中的Will QoS和Will Retain字段必須設置為0,並且有效載荷中不能包含Will Topic和Will Message字段。

  |--第3位、第4位:遺囑QoS Will QoS

      沒啥說的,遺囑也是一個publish的消息,需要確定的消息等級。

  |--第5位:遺囑保留 Will Retain

      如果遺囑消息被發布時需要保留,需要指定這一位的值。     

tips:
  保留消息是mqtt中比較重要的概念,它是統治服務器是否保留本條報文,以推送給后來訂閱者的。比如描述設備狀態的報文,這個就留在服務端就行,只要設備狀態不改變,就沒有必要修改這個報文,后續訂閱設備狀態的也能什么時候訂閱什么時候收到,非常方便。

 

  |--第6位:用戶名標志 User Name Flag

      這設置0,有效載荷就不能有了,設置1就必須有這個字段。

  |--第7位:密碼標志 Password Flag

      同上

--第9第10個字節:保持連接 Keep Alive

  保持連接(Keep Alive)是一個以秒為單位的時間間隔,表示為一個16位的字,它是指在客戶端傳輸完成一個控制報文的時刻到發送下一個報文的時刻,兩者之間允許空閑的最大時間間隔。客戶端負責保證控制報文發送的時間間隔不超過保持連接的值。

  如果沒有任何其它的控制報文可以發送,客戶端必須發送一個。保持連接的實際值是由應用指定的,一般是幾分鍾。允許的最大值是18小時12分15秒。

3.有效載荷

CONNECT報文的有效載荷(payload)包含一個或多個以長度為前綴的字段,可變報頭中的標志決定是否包含這些字段。如果包含的話,必須按這個順序出現:客戶端標識符,遺囑主題,遺囑消息,用戶名,密碼。

有個概念必須要了解--客戶端標識符 Client Identifier,也就是客戶端的唯一標識。服務端使用客戶端標識符 (ClientId) 識別客戶端。連接服務端的每個客戶端都有唯一的客戶端標識符(ClientId)。客戶端和服務端都必須使用ClientId識別兩者之間的MQTT會話相關的狀態。

客戶端標識符 (ClientId) 必須存在而且必須是CONNECT報文有效載荷的第一個字段 ,客戶端標識符必須是1.5.3節定義的UTF-8編碼字符串。

 

二、CONNACK – 確認連接請求

服務端發送CONNACK報文響應從客戶端收到的CONNECT報文。服務端發送給客戶端的第一個報文必須是CONNACK。

如果客戶端在合理的時間內沒有收到服務端的CONNACK報文,客戶端應該關閉網絡連接。合理 的時間取決於應用的類型和通信基礎設施。

1.固定報文頭

固定頭沒啥可說的的,報文類型是2.

2.可變報文頭

 

 主要有兩個字節:

--第一個字節是連接確認標志,8位里面就第0位有用,其他都是0不用管。

第0位標識的是當前會話,也就是服務端告訴客戶端你在我這的session是我新啟動的(值是0),還是原來就有的,我只是重用(值是1)

如果之前客戶端發的連接報文,讓服務端清理clientsession,那服務端的session肯定是新建的,那這個標志就是0,或者是之前客戶端就沒連過,那這個值也是0 。

如果連接報文沒有讓服務端清理clientsession,並且之前客戶端連接過,服務器用的是原來的會話,那這個值就是1 。

--第二個字節是連接返回碼

連接返回碼字段使用一個字節的無符號值【見下表】。如果服務端收到一個合法的CONNECT報文,但出於某些原因無法處理它,服務端應該嘗試發送一個包含非零返回碼(表格中的某一個)的CONNACK報文。

如果服務端發送了一個包含非零返回碼的CONNACK報文,那么它必須關閉網絡連接 。

 

 如果認為上表中的所有連接返回碼都不太合適,那么服務端必須關閉網絡連接,不需要發送CONNACK報文。

3.有效荷載

CONNACK報文沒有有效載荷。

 三、斷開連接

DISCONNECT報文是客戶端發給服務端的最后一個控制報文。表示客戶端正常斷開連接。服務端收到這個報文后,把這個客戶端的遺言也要刪除了。

1.固定頭

控制報文類型是14,其他沒啥。

2.可變頭

沒有可變頭。

3.有效載荷

沒有有效載荷。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM