3.1 CONNECT - 客戶端請求與服務器的連接
在客戶端向服務器建立網絡連接之後,從客戶端發送到服務器的第一個數據包必須是CONNECT數據包 [MQTT-3.1.0-1]。
客戶端只能通過網絡連接發送一次CONNECT數據包。服務器必須處理從客戶端發送的第二個CONNECT數據包作爲協議違規並斷開客戶端 [MQTT-3.1.0-2]。有關處理錯誤的信息,請參見第4.8節。
有效載荷包含一個或多個編碼字段。它們爲客戶端指定唯一的客戶端標識符,Will主題,Will Message,用戶名和密碼。除客戶端標識符之外的所有標識符都是可選的,它們的存在是根據變量頭中的標誌確定的。
3.1.1 Fixed header 固定標題
位 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
字節1 |
MQTT控制包類型(1) |
保留的 |
||||||
|
0 |
0 |
0 |
1 |
0 |
0 |
0 |
0 |
字節2 ... |
剩餘長度 |
剩餘長度字段
剩餘長度是變量頭的長度(10個字節)加上有效負載的長度。它以2.2.3節中描述的方式編碼。
3.1.2 Variable header 變量頭
CONNECT數據包的變量頭按以下順序包含四個字段:協議名稱,協議級別,連接標誌和保持活動。
|
描述 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
協議名稱 |
|||||||||
字節1 |
長度MSB(0) |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
字節2 |
長度LSB(4) |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
字節3 |
'M' |
0 |
1 |
0 |
0 |
1 |
1 |
0 |
1 |
字節4 |
'Q' |
0 |
1 |
0 |
1 |
0 |
0 |
0 |
1 |
字節5 |
'T' |
0 |
1 |
0 |
1 |
0 |
1 |
0 |
0 |
字節6 |
'T' |
0 |
1 |
0 |
1 |
0 |
1 |
0 |
0 |
協議名稱是UTF-8編碼的字符串,表示協議名稱“MQTT”,大寫如圖所示。MQTT規範的未來版本不會更改字符串,其偏移量和長度。
如果協議名稱不正確,則服務器可以斷開客戶端,或者可以根據其他規範繼續處理CONNECT數據包。在後一種情況下,服務器不得繼續按照此規範 [MQTT-3.1.2-1] 繼續處理CONNECT數據包。
非規範性評論
數據包檢查員(如防火牆)可以使用協議名稱來識別MQTT流量。
|
描述 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
協議級別 |
|||||||||
字節7 |
等級(4) |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
8位無符號值,表示客戶端使用的協議的修訂級別。協議版本3.1.1的協議級別字段的值爲4(0x04)。服務器必須使用CONNACK返回碼0x01(不可接受的協議級別)響應CONNECT數據包,如果服務器 [MQTT-3.1.2-2] 不支持協議級別,則斷開客戶端連接。
Connect Flags字節包含許多指定MQTT連接行爲的參數。它還指示有效載荷中是否存在字段。
位 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
|
用戶名標誌 |
密碼標誌 |
是否保留標識 |
QOS級別 |
will flag |
清楚session標識 |
保留位 |
|
字節8 |
X |
X |
X |
X |
X |
X |
X |
0 |
服務器必須驗證在CONNECT控制分組中的保留標誌被設爲零並斷開客戶端,如果它不是零 [MQTT-3.1.2-3] 。
位置: Connect Flags字節的第1位。
此位指定會話狀態的處理。
客戶端和服務器可以存儲會話狀態,以便在一系列網絡連接中繼續可靠的消息傳遞。該位用於控制會話狀態的生命週期。
如果CleanSession設置爲0,則服務器必須根據當前會話的狀態(由客戶端標識符標識)恢復與客戶端的通信。如果沒有與客戶端標識符關聯的會話,則服務器必須創建新會話。在客戶端和服務器斷開連接後,客戶端和服務器必須存儲會話 [MQTT-3.1.2-4]。斷開CleanSession設置爲0的會話後,服務器必須存儲更多的QoS 1和QoS 2消息,這些消息與客戶端在斷開連接時所擁有的任何訂閱相匹配,作爲會話狀態的一部分[ MQTT-3 .1.2- 5]。它還可以存儲符合相同標準的QoS 0消息。
如果CleanSession設置爲1,則客戶端和服務器必須丟棄任何先前的會話並開始新的會話。只要網絡連接,此會話就會持續。與此會話關聯的狀態數據不得在任何後續會話 [MQTT-3.1.2-6]中重用。
客戶端中的會話狀態包括:
·QoS 1和QoS 2消息已發送到服務器,但尚未完全確認。
·已從服務器接收但尚未完全確認的QoS 2消息。
服務器中的會話狀態包括:
·即使會話狀態的其餘部分爲空,也存在會話。
·客戶的訂閱。
·QoS 1和QoS 2消息已發送到客戶端,但尚未完全確認。
·QoS 1和QoS 2消息等待傳輸到客戶端。
·已從客戶端接收但尚未完全確認的QoS 2消息。
·可選地,QoS 0消息等待傳輸到客戶端。
保留的消息不構成服務器中會話狀態的一部分,當會話結束時,它們不能被刪除 [MQTT-3.1.2.7]。
有關存儲狀態的詳細信息和限制,請參見第4.1節。
當CleanSession設置爲1時,客戶端和服務器不需要以原子方式處理狀態刪除。
非規範性評論
爲了確保在發生故障時保持一致狀態,客戶端應重複嘗試連接CleanSession設置爲1,直到連接成功爲止。
非規範性評論
通常,客戶端將始終使用CleanSession設置爲0或CleanSession設置爲1進行連接,而不是在兩個值之間進行交換。選擇取決於應用程序。將CleanSession設置爲1的客戶端將不會收到舊的應用程序消息,並且每次連接時都必須重新訂閱它感興趣的任何主題。將CleanSession設置爲0的客戶端將接收斷開連接時發佈的所有QoS 1或QoS 2消息。因此,要確保在斷開連接時不丟失消息,請使用QoS 1或QoS 2,並將CleanSession設置爲0。
非規範性評論
當客戶端連接CleanSession設置爲0時,它請求服務器在斷開連接後保持其MQTT會話狀態。如果客戶端打算在稍後的某個時間點重新連接到服務器,則客戶端應僅與CleanSession設置爲0連接。當客戶端確定它沒有進一步用於會話時,它應該與CleanSession設置爲1進行最終連接,然後斷開連接。
位置: Connect Flags的第2位。
WILL MESSAGE : 遺囑消息
如果Will Flag設置爲1,則表示如果接受Connect請求,則Will Message必須存儲在服務器上並與網絡連接相關聯。除非在收到DISCONNECT數據包[MQTT-3.1.2-8] 後服務器刪除了Will Message,否則必須在網絡連接隨後關閉時發佈Will Message消息。
發佈遺囑消息的情況包括但不限於:
- 服務器檢測到I / O錯誤或網絡故障。
- 客戶端無法在Keep Alive時間內進行通信。
- 客戶端在未先發送DISCONNECT數據包的情況下關閉網絡連接。
- 由於協議錯誤,服務器關閉網絡連接。
如果Will Flag設置爲1,則服務器將使用Connect Flags中的Will QoS和Will Retain字段,並且有效負載中必須存在Will Topic和Will Message字段 [MQTT-3.1.2-9]。
一旦發佈或服務器已從客戶端[MQTT-3.1.2-10] 收到DISCONNECT數據包,則必須從服務器中存儲的會話狀態中刪除Will消息。
如果Will Flag設置爲0,則Connect Flags中的Will QoS和Will Retain字段必須設置爲零,並且Will Top Topic和Will Message字段不得出現在有效載荷[MQTT-3.1.2-11]中。
如果將Will Flag設置爲0,則當此網絡連接結束時,不得發佈Will Message消息[MQTT-3.1.2-12] 。
服務器應該立即發佈Will Messages。在服務器關閉或故障的情況下,服務器可以推遲發佈Will Messages直到後續重新啓動。如果發生這種情況,服務器遇到故障和發佈Will Message之間可能會有一段延遲。
QOS:Quality of Service
位置: Connect Flags的第4位和第3位。
這兩個位指定發佈Will Message時要使用的QoS級別。
如果Will Flag設置爲0,則Will QoS必須設置爲0 (0x00)[MQTT-3.1.2-13]。
如果Will Flag設置爲1,則Will QoS的值可以是0(0x00),1(0x01)或2(0x02)。它不能是3(0x03)[MQTT-3.1.2-14]。
位置: Connect Flags的第5位。
此位指定在發佈時是否保留Will Message。
如果Will Flag設置爲0,則Will Retain Flag必須設置爲0 [MQTT-3.1.2-15]。
如果Will Flag設置爲1:
- 如果Will Retain設置爲0,則服務器必須將Will Message作爲非保留消息 [MQTT-3.1.2-16]發佈。
- 如果Will Retain設置爲1,則服務器必須將Will Message作爲保留消息[MQTT-3.1.2-17]發佈。
位置: Connect Flags的第7位。
如果用戶名標誌設置爲0,則有效負載 [MQTT-3.1.2-18]中不得出現用戶名。
如果用戶名標誌設置爲1,則有效負載 [MQTT-3.1.2-19]中必須存在用戶名。
位置: Connect Flags字節的第6位。
如果密碼標誌設置爲0,則有效負載 [MQTT-3.1.2-20]中不得出現密碼。
如果密碼標誌設置爲1,則有效負載 [MQTT-3.1.2-21]中必須存在密碼。
如果用戶名標誌設置爲0,則密碼標誌必須設置爲0 [MQTT-3.1.2-22]。
位 |
7 |
6 |
五 |
4 |
3 |
2 |
1 |
0 |
字節9 |
保持活力MSB |
|||||||
字節10 |
保持活着LSB |
Keep Alive是以秒爲單位測量的時間間隔。表示爲16位字,它是客戶端完成發送一個控制數據包的點與它開始發送下一個控制數據包的點之間允許經過的最大時間間隔。客戶有責任確保發送的控制數據包之間的間隔不超過保持活動值。在沒有發送任何其他控制數據包的情況下,客戶端必鬚髮送PINGREQ數據包 [MQTT-3.1.2-23]。
無論Keep Alive值如何,客戶端都可以隨時發送PINGREQ,並使用PINGRESP確定網絡和服務器是否正常工作。
如果Keep Alive值爲非零且服務器在Keep Alive時間段的一倍半內沒有從客戶端收到控制數據包,它必須斷開與客戶端的網絡連接,就好像網絡發生故障一樣 [MQTT -3.1.2-24] 。
如果客戶端在發送PINGREQ後的一段合理時間內沒有收到PINGRESP數據包,它應該關閉與服務器的網絡連接。
保持活動值爲零(0)具有關閉保持活動機制的效果。這意味着,在這種情況下,服務器不需要以不活動爲由斷開客戶端。
請注意,允許服務器隨時斷開它確定爲無效或無響應的客戶端,無論該客戶端提供的保持活動值如何。
非規範性評論
Keep Alive的實際值是特定於應用程序的; 通常這是幾分鐘。最大值爲18小時12分15秒。
3.1.2.11 變量頭非規範性示例
3.1.3 Payload
CONNECT數據包的有效負載包含一個或多個長度前綴字段,其存在由變量頭中的標誌確定。這些字段(如果存在)必須出現在客戶端標識符,主題,消息,用戶名,密碼[MQTT-3.1.3-1]的順序中。
3.1.3.1 Client Identifier 客戶端 id必須唯一
客戶端標識符(ClientId)將客戶端標識爲服務器。連接到服務器的每個客戶端都有一個唯一的ClientId。客戶端和服務器必須使用ClientId來識別它們與客戶端和服務器之間的MQTT會話相關的狀態 [MQTT-3.1.3-2] 。
客戶端標識符(ClientId)必須存在,並且必須是CONNECT數據包有效負載 [MQTT-3.1.3-3]中的第一個字段。
ClientId必須是第1.5.3 節[MQTT-3.1.3-4]中定義的UTF-8編碼字符串。
服務器必須允許ClientIds,其長度在1到23個UTF-8編碼字節之間,並且只包含字符
“0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ” [MQTT-3.1.3-5] 。
服務器可以允許包含超過23個編碼字節的ClientId。服務器可以允許ClientId包含上面給出的列表中未包含的字符。
服務器可以允許客戶端提供長度爲零字節的ClientId,但是如果它這樣做,則服務器必須將其視爲特殊情況併爲該客戶端分配唯一的ClientId。它必須處理CONNECT數據包,就像客戶端提供了唯一的ClientId [MQTT-3.1.3-6]一樣。
如果客戶端提供零字節ClientId,則客戶端還必須將CleanSession設置爲1 [MQTT-3.1.3-7]。
如果客戶端提供一個零字節的ClientId,其CleanSession設置爲0,則服務器必須使用CONNACK返回代碼0x02(標識符被拒絕)響應CONNECT數據包,然後關閉網絡連接 [MQTT-3.1.3-8] 。
如果服務器拒絕ClientId,它必須使用CONNACK返回代碼0x02(標識符被拒絕)響應CONNECT數據包,然後關閉網絡連接 [MQTT-3.1.3-9] 。
非規範性評論
客戶端實現可以提供生成隨機ClientId的便捷方法。當CleanSession設置爲0時,應該主動阻止使用這種方法。
如果Will Flag設置爲1,則Will Topic是有效負載中的下一個字段。Will Topic必須是第1.5.3 節[MQTT-3.1.3-10]中定義的UTF-8編碼字符串。
如果Will Flag設置爲1,則Will Message是有效載荷中的下一個字段。Will Message定義了要發佈到Will Topic的應用程序消息,如3.1.2.5節所述。該字段由兩個字節長度組成,後跟Will Message的有效負載,表示爲零個或多個字節的序列。長度給出了後面數據中的字節數,不包括長度本身佔用的2個字節。
當Will Message發佈到Will Topic時,其有效負載僅包含該字段的數據部分,而不是前兩個長度字節。
如果用戶名標誌設置爲1,則這是有效負載中的下一個字段。用戶名必須是第1.5.3 節[MQTT-3.1.3-11]中定義的UTF-8編碼字符串。 它可以由服務器用於身份驗證和授權。
如果密碼標誌設置爲1,則這是有效負載中的下一個字段。密碼字段包含0到65535字節的二進制數據,前綴爲兩字節長度字段,表示二進制數據使用的字節數(它不包括長度字段本身佔用的兩個字節)。
位 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
字節1 |
數據長度MSB |
|||||||
字節2 |
數據長度LSB |
|||||||
字節3 .... |
數據,如果長度> 0。 |
3.1.4 Response 迴應
請注意,服務器可以在同一TCP端口或其他網絡端點上支持多個協議(包括此協議的早期版本)。如果服務器確定協議是MQTT 3.1.1,那麼它將驗證連接嘗試,如下所示。
1. 如果服務器在建立網絡連接後的合理時間內未收到CONNECT數據包,則服務器應該關閉連接。
2. 如果CONNECT數據包不符合[MQTT-3.1.4-1],它必須驗證CONNECT數據包是否符合第3.1 節並關閉網絡連接而不發送CONNACK 。
3. 服務器可以檢查CONNECT數據包的內容是否滿足任何進一步的限制,並且可以執行身份驗證和授權檢查。如果這些檢查中的任何一個失敗,它應該發送一個帶有非零返回碼的適當的CONNACK響應,如3.2節所述,它必須關閉網絡連接。
如果驗證成功,則服務器執行以下步驟。
1. 如果ClientId表示已連接到服務器的客戶端,則服務器必須斷開現有客戶端[MQTT-3.1.4-2]。
2. 服務器必須執行第3.1.2.4 節[MQTT-3.1.4-3]中描述的CleanSession處理。
3. 服務器必須使用包含零返回碼[MQTT-3.1.4-4] 的CONNACK包來確認CONNECT數據包。
4. 啓動消息傳遞並保持活動監控。
允許客戶端在發送CONNECT數據包後立即發送更多控制數據包; 客戶端無需等待CONNACK數據包從服務器到達。如果服務器拒絕CONNECT,它必須在CONNECT數據包 [MQTT-3.1.4-5] 之後不處理客戶端發送的任何數據。
非規範性註釋
客戶端通常等待CONNACK數據包,但是,如果客戶端在收到CONNACK之前利用其自由發送控制數據包,則可能會簡化客戶端實施,因爲它不必警告連接狀態。客戶端接受,如果服務器拒絕連接,則在從服務器接收CONNACK數據包之前發送的任何數據都將不會被處理。