MQTT入門介紹(一)
一.MQTT簡述
MQTT(Message Queuing Telemetry Transport,消息隊列遙測傳輸協議),是一種基於發布/訂閱(publish/subscribe)模式的"輕量級"通訊協議,該協議構建於TCP/IP協議上,由IBM在1999年發布。MQTT最大優點在於,可以以極少的代碼和有限的帶寬,為連接遠程設備提供實時可靠的消息服務。作為一種低開銷、低帶寬占用的即時通訊協議,使其在物聯網、小型設備、移動應用等方面有較廣泛的應用。
MQTT是一個基於客戶端-服務器的消息發布/訂閱傳輸協議。MQTT協議是輕量、簡單、開放和易於實現的,這些特點使它適用范圍非常廣泛。在很多情況下,包括受限的環境中,如:機器與機器(M2M)通信和物聯網(IoT)。其在,通過衛星鏈路通信傳感器、偶爾撥號的醫療設備、智能家居、及一些小型化設備中已廣泛使用。
二.設計規范
由於物聯網的環境是非常特別的,所以MQTT遵循以下設計原則:
(1)精簡,不添加可有可無的功能;
(2)發布/訂閱(Pub/Sub)模式,方便消息在傳感器之間傳遞;
(3)允許用戶動態創建主題,零運維成本;
(4)把傳輸量降到最低以提高傳輸效率;
(5)把低帶寬、高延遲、不穩定的網絡等因素考慮在內;
(6)支持連續的會話控制;
(7)理解客戶端計算能力可能很低;
(8)提供服務質量管理;
(9)假設數據不可知,不強求傳輸數據的類型與格式,保持靈活性。
三.主要特性
MQTT協議工作在低帶寬、不可靠的網絡的遠程傳感器和控制設備通訊而設計的協議,它具有以下主要的幾項特性:
(1)使用發布/訂閱消息模式,提供一對多的消息發布,解除應用程序耦合。
這一點很類似於XMPP,但是MQTT的信息冗余遠小於XMPP,,因為XMPP使用XML格式文本來傳遞數據。
(2)對負載內容屏蔽的消息傳輸。
(3)使用TCP/IP提供網絡連接。
主流的MQTT是基於TCP連接進行數據推送的,但是同樣有基於UDP的版本,叫做MQTT-SN。這兩種版本由於基於不同的連接方式,優缺點自然也就各有不同了。
(4)有三種消息發布服務質量:
Qos = 0; "至多一次",消息發布完全依賴底層TCP/IP網絡。會發生消息丟失或重復。這一級別可用於如下情況,環境傳感器數據,丟失一次讀記錄無所謂,因為不久后還會有第二次發送。這一種方式主要普通APP的推送,倘若你的智能設備在消息推送時未聯網,推送過去沒收到,再次聯網也就收不到了。
Qos = 1; "至少一次",確保消息到達,但消息重復可能會發生。
Qos = 0; "只有一次",確保消息到達一次。在一些要求比較嚴格的計費系統中,可以使用此級別。在計費系統中,消息重復或丟失會導致不正確的結果。這種最高質量的消息發布服務還可以用於即時通訊類的APP的推送,確保用戶收到且只會收到一次。
(5)小型傳輸,開銷很小(固定長度的頭部是2字節),協議交換最小化,以降低網絡流量。
這就是為什么在介紹里說它非常適合"在物聯網領域,傳感器與服務器的通信,信息的收集",要知道嵌入式設備的運算能力和帶寬都相對薄弱,使用這種協議來傳遞消息再適合不過了。
(6)使用Last Will和Testament特性通知有關各方客戶端異常中斷的機制。
Last Will:即遺言機制,用於通知同一主題下的其他設備發送遺言的設備已經斷開了連接。
Testament:遺囑機制,功能類似於Last Will。
四.相關術語
(1) 網絡連接(NetWork Connection)
MQTT使用的底層傳輸協議基礎設施。
1) 客戶端使用它連接服務端
2) 它提供有序的、可靠的、雙向字節流傳輸
(2) 客戶端(Client)
使用MQTT的程序或設備。客戶端總是通過網絡連接到服務端。它可以:
1) 發布應用消息給其他相關的客戶端
2) 訂閱以請求接收相關的應用消息
3) 取消訂閱以移除接受應用消息的請求
4) 從服務端斷開連接
(3) 服務端(Server)
一個程序或者設備、作為發送消息的客戶端和請求訂閱的客戶端端之間的中介。服務端:
1) 接受來自客戶端的網絡連接
2) 接受客戶端發布的應用消息
3) 處理客戶端的訂閱和取消訂閱請求
4) 轉發應用消息給符合條件的已訂閱客戶端
(4) 訂閱(Subscription)
訂閱包含一個主題過濾器(Topic Filter)和一個最大的服務質量(QoS)等級。訂閱與單個會話(Session)關聯。會話可以包含對於一個的訂閱。會話的每個訂閱都有一個不同的主題過濾器。
(5) 主題名(Topic Name)
附加在應用消息上的一個標簽,服務端已知且與訂閱匹配。服務端發送應用消息的一個副本給每一個匹配的客戶端訂閱。
(6) 主題過濾器(Topic Filter)
訂閱中包含的一個表達式,用於表示相關的一個或多個主題。主題過濾器可以使用通配符
(7) 會話(Session)
客戶端和服務端之間的狀態交互。一些會話持續時間長和網絡連接一樣,另一些可以在客戶端和服務端的多個連續網絡連接間擴展。
(8) 控制報文(MQTT Control Packet)
通過網絡連接發送的信息數據包。MQTT規范定義了十四種不同類型的控制報文,其中一個(PUBLISH報文)用於傳輸應用消息。
五.MQTT 控制報文
MQTT協議通過交換預定義的MQTT控制報文來通信。MQTT控制報文由三部分組成,分別是:固定報頭(所有報文都包含)、可變報頭(部分報文包含)、有效載荷(部分報文包含)
Fixed header |
固定報頭 |
Variable header |
可變報頭 |
Payload |
有效載荷 |
(1)固定報頭 Fixed header
每個MQTT控制報文都包含一個固定報頭,固定報頭的格式如下:
Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
byte 1 |
MQTT控制報文的類型 |
用於指定報文類型的標志位 |
||||||
Byte 2 ... |
剩余長度 |
MQTT 控制報文的類型(固定報頭第一個字節,二進制7-4):
名字 |
值 |
報文流動方向 |
描述 |
Reserved |
0 |
禁止 |
保留 |
CONNECT |
1 |
客戶端到服務端 |
連接服務端 |
CONNACK |
2 |
服務端到客戶端 |
確認連接請求 |
PUBLISH |
3 |
兩個方向都允許 |
發布消息 |
PUBACK |
4 |
兩個方向都允許 |
發布確認 |
PUBREC |
5 |
兩個方向都允許 |
發布收到(QoS2,第一步) |
PUBREL |
6 |
兩個方向都允許 |
發布釋放(QoS2,第二步) |
PUBCOMP |
7 |
兩個方向都允許 |
發布完成(QoS2,第三步) |
SUBSCRIBE |
8 |
客戶端到服務端 |
訂閱主題 |
SUBACK |
9 |
服務端到客戶端 |
訂閱確認 |
UNSUBSCRIBE |
10 |
客戶端到服務端 |
取消訂閱 |
UNSUBACK |
11 |
服務端到客戶端 |
取消訂閱確認 |
PINGREQ |
12 |
客戶端到服務端 |
心跳請求 |
PINGRESP |
13 |
服務端到客戶端 |
心跳響應 |
DISCONNECT |
14 |
客戶端到服務端 |
斷開連接 |
Reserved |
15 |
禁止 |
保留 |
報文標志Flag(固定報頭,第一個字節3-0)
每種報文都對應了相關的標志位,標志位如下表所列,如果收到非法的標志,接收者 必須關閉網絡連接。報文標志列表如下:
控制報文 |
固定報頭標志 |
Bit 3 |
Bit 2 |
Bit 1 |
Bit 0 |
CONNECT |
Reserved |
0 |
0 |
0 |
0 |
CONNACK |
Reserved |
0 |
0 |
0 |
0 |
PUBLISH |
Userd in MQTT 3.1.1 |
DUP1 |
QoS2 |
QoS2 |
RETAIN3 |
PUBACK |
Reserved |
0 |
0 |
0 |
0 |
PUBREC |
Reserved |
0 |
0 |
0 |
0 |
PUBREL |
Reserved |
0 |
0 |
1 |
0 |
PUBCOMP |
Reserved |
0 |
0 |
0 |
0 |
SUBSCRIBE |
Reserved |
0 |
0 |
1 |
0 |
SUBACK |
Reserved |
0 |
0 |
0 |
0 |
UNSUBSCRIBE |
Reserved |
0 |
0 |
1 |
0 |
UNSUBACK |
Reserved |
0 |
0 |
0 |
0 |
PINGREQ |
Reserved |
0 |
0 |
0 |
0 |
PINGRESP |
Reserved |
0 |
0 |
0 |
0 |
DISCONNECT |
Reserved |
0 |
0 |
0 |
0 |
DUP1 = 控制報文的重復分發標志
QoS2 = PUBLISH報文的服務質量等級
RETAIN3 = PUBLISH報文的保留標志
剩余長度(固定報頭,第二個字節開始,最大4個字節):
剩余長度(Remaining Length)表示當前報文剩余部分的字節數,包含可變報頭和負載的數據。剩余長度不包括用於編碼剩余長度字段本身的字節數。
剩余長度字段使用一個變長度編碼方案,對於小於128的值它使用單字節編碼。更大的值下面的方式處理。低7位有效位用於編碼數據,最高有效位用於指示是否有更多的字節,且按照大端方式進行編碼。因此每個字節可以編碼128個數值和一個延續位。剩余長度字節最大4個字節。
字節數 |
最小值 |
最大值 |
1 |
0(0x00) |
127(0x7F) |
2 |
128(0x80,0x01) |
16383(0xFF,0x7F) |
3 |
16384(0x80,0x80,0x01) |
2097151(0xFF,0xFF,0x7F) |
4 |
2097152(0x80,0x80,0x80,0x01) |
268435455(0xFF,0xFF,0xFF,0x7F) |
(2)可變報頭 Variable header
某些MQTT控制報文包含一個可變頭部分。它在固定報頭和負載之間。可變報頭的內容根據報文類型的不同而不同,可變報頭的報文標識符字段存在於多個類型的報文里。
報文標識符結構如下:
Bit |
7-0 |
byte 1 |
報文標識符MSB(字符串長度的最高有效字節) |
byte 2 |
報文標識符LSB(字符串長度的最低有效字節) |
如下列舉了那些MQTT控制報文需要報文標識符
控制報文 |
報文標識符字段 |
CONNECT |
不需要 |
CONNACK |
不需要 |
PUBLISH |
需要(如果QoS > 0) |
PUBACK |
需要 |
PUBREC |
需要 |
PUBREL |
需要 |
PUBCOMP |
需要 |
SUBSCRIBE |
需要 |
SUBACK |
需要 |
UNSUBSCRIBE |
需要 |
UNSUBACK |
需要 |
PINGREQ |
不需要 |
PINGRESP |
不需要 |
DISCONNECT |
不需要 |
(3)有效載荷 Payload
某些MQTT控制報文在報文的最后部分包含一個有效載荷,如下是包含有效載荷的控制報文列表:
控制報文 |
報文標識符字段 |
CONNECT |
需要 |
CONNACK |
不需要 |
PUBLISH |
可選 |
PUBACK |
不需要 |
PUBREC |
不需要 |
PUBREL |
不需要 |
PUBCOMP |
不需要 |
SUBSCRIBE |
需要 |
SUBACK |
需要 |
UNSUBSCRIBE |
需要 |
UNSUBACK |
不需要 |
PINGREQ |
不需要 |
PINGRESP |
不需要 |
DISCONNECT |
不需要 |