2.1 MQTT控制包的結構
MQTT協議通過以定義的方式交換一系列MQTT控制數據包來工作。本節介紹這些數據包的格式。
MQTT控制包最多由三部分組成,總是按照以下順序組成,如圖2.1所示 - MQTT控制包的結構。
固定標頭,存在於所有MQTT控制數據包中 |
變量頭,存在於某些MQTT控制包中 |
有效負載,存在於某些MQTT控制數據包中 |
2.2固定標題
每個MQTT控制包都包含一個固定的頭。圖2.2-固定標題格式說明了固定標題格式。
位 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
字節1 |
MQTT控制包類型 |
特定於每個MQTT控制數據包類型的標誌 |
||||||
字節2 ... |
剩餘長度 |
2.2.1 MQTT控制包類型
位置:字節1,位7-4。
表示爲4位無符號值,值列於表2.1 - 控制數據包類型。
名稱 |
值 |
流動方向 |
描述 |
|
Reserved |
0 |
被禁止 |
保留的 |
|
CONNECT |
1 |
客戶端到服務器 |
客戶端請求連接到服務器 |
|
CONNACK |
2 |
服務器到客戶端 |
連接確認 |
|
PUBLISH |
3 |
客戶端到服務器 或 服務器到客戶端 |
發佈消息 |
|
PUBACK |
4 |
客戶端到服務器 或 服務器到客戶端 |
發佈確認 |
|
PUBREC |
五 |
客戶端到服務器 或 服務器到客戶端 |
收到發佈(保證交付第1部分) |
|
PUBREL |
6 |
客戶端到服務器 或 服務器到客戶端 |
發佈發佈(保證交付第2部分) |
|
PUBCOMP |
7 |
客戶端到服務器 或 服務器到客戶端 |
發佈完整(保證交付第3部分) |
|
SUBSCRIBE |
8 |
客戶端到服務器 |
客戶訂閱請求 |
|
SUBACK |
9 |
服務器到客戶端 |
訂閱確認 |
|
UNSUBSCRIBE |
10 |
客戶端到服務器 |
取消訂閱請求 |
|
UNSUBACK |
11 |
服務器到客戶端 |
取消訂閱確認 |
|
PINGREQ |
12 |
客戶端到服務器 |
PING請求 |
|
PINGRESP |
13 |
服務器到客戶端 |
PING響應 |
|
DISCONNECT |
14 |
客戶端到服務器 |
客戶端優雅斷開並告訴服務器 |
|
Reserved |
15 |
被禁止 |
保留的 |
|
2.2.2 Flags 標誌
固定報頭中字節1的其餘位[3-0]包含特定於每個MQTT控制包類型的標誌,如下面的表2.2-標誌位所列。如果標誌位在表2.2中標記爲“保留” - 標誌位,則保留供將來使用,並且必須設置爲該表 [MQTT-2.2.2-1]中列出的值。如果收到無效標誌,接收方必須關閉網絡連接[MQTT-2.2.2-2] 。有關處理錯誤的詳細信息,請參見第4.8 節
控制包 |
固定標頭標誌 |
第3位 |
第2位 |
第1位 |
位0 |
CONNECT |
保留的 |
0 |
0 |
0 |
0 |
CONNACK |
保留的 |
0 |
0 |
0 |
0 |
PUBLISH |
用於MQTT 3.1.1 |
DUP 1 |
QoS 2 |
QoS 2 |
保留3 |
PUBACK |
保留的 |
0 |
0 |
0 |
0 |
PUBREC |
保留的 |
0 |
0 |
0 |
0 |
PUBREL |
保留的 |
0 |
0 |
1 |
0 |
PUBCOMP |
保留的 |
0 |
0 |
0 |
0 |
SUBSCRIBE |
保留的 |
0 |
0 |
1 |
0 |
SUBACK |
保留的 |
0 |
0 |
0 |
0 |
UNSUBSCRIBE |
保留的 |
0 |
0 |
1 |
0 |
UNSUBACK |
保留的 |
0 |
0 |
0 |
0 |
PINGREQ |
保留的 |
0 |
0 |
0 |
0 |
PINGRESP |
保留的 |
0 |
0 |
0 |
0 |
DISCONNECT |
保留的 |
0 |
0 |
0 |
0 |
DUP 1 =重複發送發佈控制包
QoS 2 =發佈服務質量
RETAIN 3 = 發佈保留標誌
有關PUBLISH控制包中DUP,QoS和RETAIN標誌的說明,請參見第3.3.1節。
2.2.3 Remaining Length 剩餘長度
位置:從字節2開始。
剩餘長度是當前數據包中剩餘的字節數,包括變量頭和有效負載中的數據。剩餘長度不包括用於編碼剩餘長度的字節。
剩餘長度使用可變長度編碼方案進行編碼,該方案使用單個字節用於最多127的值。較大的值按如下方式處理。每個字節的最低有效7位對數據進行編碼,最高有效位用於指示表示中有後續字節。因此,每個字節編碼128個值和“連續位”。“剩餘長度”字段中的最大字節數爲四。
非規範性評論
例如,64位十進制編碼爲單字節,十進制值64,十六進制0x40。數字321十進制(= 65 + 2 * 128)被編碼爲兩個字節,最不重要的是第一個。第一個字節是65 + 128 = 193.注意,最高位設置爲至少指示一個後續字節。第二個字節是2。
非規範性評論
這允許應用程序發送大小高達268,435,455(256 MB)的控制數據包。這個數字在線上的表示是:0xFF,0xFF,0xFF,0x7F。
表2.4顯示了由增加的字節數表示的剩餘長度值。
數字 |
從 |
至 |
1 |
0(0x00) |
127(0x7F) |
2 |
128(0x80,0x01) |
16 383(0xFF,0x7F) |
3 |
16 384(0x80,0x80,0x01) |
2 097 151(0xFF,0xFF,0x7F) |
4 |
2 097 152(0x80,0x80,0x80,0x01) |
268 435 455(0xFF,0xFF,0xFF,0x7F) |
非規範性評論
將非負整數(X)編碼爲可變長度編碼方案的算法如下:
do 283
encodedByte = X MOD 128 284
X = X DIV 128 285
// if there are more data to encode, set the top bit of this byte 286
if ( X > 0 ) 287
encodedByte = encodedByte OR 128 288
endif 289
'output' encodedByte 290
while ( X > 0 )
其中MOD是模運算符(C中的%),DIV 是整數除法(/在C中),OR是按位或(|在C中)。
非規範性評論
解碼剩餘長度字段的算法如下:
multiplier = 1 299
value = 0 300
do 301
encodedByte = 'next byte from stream' 302
value += (encodedByte AND 127) * multiplier 303
multiplier *= 128 304
if (multiplier > 128*128*128) 305
throw Error(Malformed Remaining Length) 306
while ((encodedByte AND 128) != 0)
其中AND是按位和運算符(& in C)。
當此算法終止時,value包含Remaining Length值。
2.3 Variable header 變量頭
某些類型的MQTT控制數據包包含可變標頭組件。它位於固定標頭和有效負載之間。變量頭的內容根據數據包類型而有所不同。變量頭的包標識符字段在幾種包類型中是通用的。
2.3.1包標識符
位 |
7 |
6 |
五 |
4 |
3 |
2 |
1 |
0 |
字節1 |
包標識符MSB |
|||||||
字節2 |
包標識符LSB |
許多控制分組類型的可變報頭組件包括2字節分組標識符字段。這些控制數據包是PUBLISH(其中QoS> 0),PUBACK,PUBREC,PUBREL,PUBCOMP,SUBSCRIBE,SUBACK,UNSUBSCRIBE,UNSUBACK。
SUBSCRIBE,UNSUBSCRIBE和PUBLISH(在QoS> 0的情況下)控制數據包必須包含非零的16位數據包標識符 [MQTT-2.3.1-1]。每次客戶端發送這些類型之一的新數據包時,它必須爲其分配當前未使用的數據包標識符 [MQTT-2.3.1-2]。如果客戶端重新發送特定的控制數據包,那麼它必須在後續重新發送該數據包時使用相同的數據包標識符。客戶端處理完相應的確認數據包後,數據包標識符可以重用。在QoS 1 PUBLISH的情況下,這是相應的PUBACK; 在QoS 2的情況下,它是PUBCOMP。對於SUBSCRIBE或UNSUBSCRIBE,它是相應的SUBACK或UNSUBACK [MQTT-2.3.1-3]。 當服務器發送QoS> 0 [MQTT-2.3.1-4] 的PUBLISH時,相同的條件適用於服務器。
如果其QoS值設置爲0,則PUBLISH數據包 不得包含數據包標識符[MQTT-2.3.1-5]。
PUBACK,PUBREC或PUBREL數據包必須包含與最初發送的PUBLISH數據包相同的數據包標識符 [MQTT-2.3.1-6]。類似地,SUBACK和UNSUBACK必須包含分別在相應的SUBSCRIBE和UNSUBSCRIBE數據包中使用的數據包標識符 [MQTT-2.3.1-7]。
表2.5 - 包含數據包標識符的控制數據包中列出了需要數據包標識符的控制數據包。
控制包 |
數據包標識符字段 |
CONNECT |
沒有 |
CONNACK |
沒有 |
PUBLISH |
是(如果QoS> 0) |
PUBACK |
是 |
PUBREC |
是 |
PUBREL |
是 |
PUBCOMP |
是 |
SUBSCRIBE | |
SUBACK |
是 |
UNSUBSCRIBE |
是 |
UNSUBACK |
是 |
PINGREQ |
沒有 |
PINGRESP |
沒有 |
DISCONNECT |
沒有 |
客戶端和服務器彼此獨立地分配數據包標識符。因此,客戶端服務器對可以使用相同的數據包標識符參與併發消息交換。
非規範性評論
客戶端可以發送帶有數據包標識符0x1234的PUBLISH數據包,然後在收到其發送的PUBLISH的PUBACK之前,從其服務器接收帶有數據包標識符0x1234的不同PUBLISH。
客戶端服務器
PUBLISH Packet Identifier = 0x1234 --- à
ß -發佈數據包標識符= 0x1234
PUBACK數據包標識符= 0x1234 --- à
ß-- PUBACK數據包標識符= 0x1234
2.4 Payload 有效載荷
某些MQTT控制數據包包含有效負載作爲數據包的最後部分,如第3章所述。在PUBLISH數據包的情況下,這是應用程序消息。表2.6 - 包含有效負載的控制數據包列出了需要有效負載的控制數據包。
控制包 |
有效載荷 |
CONNECT |
需要 |
CONNACK |
沒有 |
PUBLISH |
可選的 |
PUBACK |
沒有 |
PUBREC |
沒有 |
PUBREL |
沒有 |
PUBCOMP |
沒有 |
SUBSCRIBE |
需要 |
SUBACK |
需要 |
UNSUBSCRIBE |
需要 |
UNSUBACK |
沒有 |
PINGREQ |
沒有 |
PINGRESP |
沒有 |
DISCONNECT |
沒有 |
裏面可能有些google翻譯不準的地方請大家多多指正!