最近一直做物聯網方面的開發,以下內容關於使用MQTT過程中遇到問題的記錄以及需要掌握的機制原理,主要講解理論。
背景
MQTT是IBM開發的一個即時通訊協議。MQTT構建於TCP/IP協議上,面向M2M和物聯網IoT的連接協議,采用輕量級發布和訂閱消息傳輸機制。Mosquitto是一款實現了 MQTT v3.1 協議的開源消息代理軟件,提供輕量級的,支持發布/訂閱的的消息推送模式,使設備對設備之間的短消息通信簡單易用。
基本概念
【MQTT協議特點】——相比於RESTful架構的物聯網系統,MQTT協議借助消息推送功能,可以更好地實現遠程控制。
【MQTT協議角色】——在RESTful架構的物聯網系統,包含兩個角色客戶端和服務器端,而在MQTT協議中包括發布者,代理器(服務器)和訂閱者。

- MQTT客戶端
一個使用MQTT協議的應用程序或者設備,它總是建立到服務器的網絡連接。客戶端可以:
發布其他客戶端可能會訂閱的信息
訂閱其它客戶端發布的消息
退訂或刪除應用程序的消息
斷開與服務器連接
- MQTT服務器
MQTT服務器以稱為“消息代理”(Broker),可以是一個應用程序或一台設備。它是位於消息發布者和訂閱者之間,它可以:
接受來自客戶的網絡連接
接受客戶發布的應用信息
處理來自客戶端的訂閱和退訂請求
向訂閱的客戶轉發應用程序消息
【MQTT協議消息】——MQTT中的消息可理解為發布者和訂閱者交換的內容(負載),這些消息包含具體的內容,可以被訂閱者使用。
【MQTT協議主題】——MQTT中的主題可理解為相同類型或相似類型的消息集合。
iOS庫
iOS 選擇第三方庫-github這個內容相對比較詳細,目前我是用的MQTTKIT
MQTT機制原理
以下 內容為,我在使用過程中需要掌握的基本知識要點
-
MQTT基於TCP/IP,支持Qos,輕量級的 machine-to-machine 應用層協議.
-
采用C/S模式,實現發布/訂閱機制(publish/subscribe)
-
使用username / password 登錄, clientId作為唯一標示符。使用過程中,如果cliendId 重復,會頂掉前一個使用者,另外 還有權限問題。
-
主題
MQTT是通過主題對消息進行分類的,本質上就是一個UTF-8的字符串,不過可以通過反斜杠表示多個層級關系。允許使用通配符訂閱主題,但是並不允許使用通配符廣播。
主題范例 關於Topic通配符
/:用來表示層次,比如a/b,a/b/c。
'#':表示匹配>=0個層次,比如a/#就匹配a/,a/b,a/b/c。
單獨的一個#表示匹配所有。
不允許 a#和a/#/c。
+:表示匹配一個層次,例如a/+匹配a/b,a/c,不匹配a/b/c。
單獨的一個+是允許的,a+不允許,a/+/b不允許
- 服務質量QoS
為了滿足不同的場景,MQTT支持三種不同級別的服務質量(Quality of Service,QoS)為不同場景提供消息可靠性:
級別0:盡力而為。消息發送者會想盡辦法發送消息,但是遇到意外並不會重試。這一級別會發生消息丟失或重復,消息發布依賴於底層TCP/IP網絡。即:<=1
級別1:至少一次。消息接收者如果沒有知會或者知會本身丟失,消息發送者會再次發送以保證消息接收者至少會收到一次,當然可能造成重復消息。即:>=1
級別2:恰好一次。保證這種語義肯定會減少並發或者增加延時,不過丟失或者重復消息是不可接受的時候,級別2是最合適的。
-
消息體(2個字節)
-
消息類型
-
心跳
Client有責任發送KeepAliveTime時長告訴給Server。在一個時長內,發送PINGREQ,Server發送PINGRES確認。
Server在1.5個時長內未收到PINGREQ,就斷開連接。
Client在1個時長內未收到PINGRES,斷開連接。
一般來說,時長設置為幾個分鍾。 -
RETAIN(保持)
僅針對PUBLISH消息。不同值,不同含義:
1:表示發送的消息需要一直持久保存(不受服務器重啟影響),不但要發送給當前的訂閱者,並且以后新來的訂閱了此Topic name的訂閱者會馬上得到推送。
備注:新來乍到的訂閱者,只會取出最新的一個RETAIN flag = 1的消息推送。
0:僅僅為當前訂閱者推送此消息。
優勢
設計思想是開源、可靠、輕巧、簡單,MQTT的傳輸格式非常精小,最小的數據包只有2個比特,且無應用消息頭。MQTT可以保證消息的可靠性,它包括三種不同的服務質量(最多只傳一次、最少被傳一次、一次且只傳一次),如果客戶端意外掉線,可以使用“遺願”發布一條消息,同時支持持久訂閱。MQTT在物聯網以及移動應用中的優勢有:
-
可靠傳輸。MQTT可以保證消息可靠安全的傳輸,並可以與企業應用簡易集成。
-
消息推送。支持消息實時通知、豐富的推送內容、靈活的Pub-Sub以及消息存儲和過濾。
-
低帶寬、低耗能、低成本。占用移動應用程序帶寬小,並且帶寬利用率高,耗電量較少。
參考文檔
作者:踐行者
鏈接:http://www.jianshu.com/p/93d80dd50410
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
MQTT簡介
MQTT(Message Queuing Telemetry Transport,消息隊列遙測傳輸)是IBM開發的一個即時通訊協議。它的設計思想是輕巧、開放、簡單、規范,因此易於實現。這些特點使得它對很多場景來說都是很好的選擇,包括受限的環境如機器與機器的通信(M2M)以及物聯網環境(IoT),這些場景要求很小的代碼封裝或者網絡帶寬非常昂貴。
MQTT協議是為大量計算能力有限,且工作在低帶寬、不可靠的網絡的遠程傳感器和控制設備通訊而設計的協議,它具有以下主要的幾項特性:
- 使用發布(Publish)/訂閱/(Subscribe)消息模式,提供一對多的消息發布,解除應用程序耦合
- 對負載內容屏蔽的消息傳輸
- 使用TCP/IP提供網絡連接
- 有三種消息發布服務質量
- “至多一次”,消息發布完全依賴底層 TCP/IP 網絡。會發生消息丟失或重復。這一級別可用於如下情況,環境傳感器數據,丟失一次讀記錄無所謂,因為不久后還會有第二次發送。
- “至少一次”,確保消息到達,但消息重復可能會發生。
- “只有一次”,確保消息到達一次。這一級別可用於如下情況,在計費系統中,消息重復或丟失會導致不正確的結果。
- 小型傳輸,開銷很小(固定長度的頭部是 2 字節),協議交換最小化,以降低網絡流量
- 使用 Last Will 和 Testament 特性通知有關各方客戶端異常中斷的機制
簡單的說MQTT協議是一個輕量級的即時通訊協議。因為它被運用在一些硬件和網絡不太好的環境,所以它對設備的要求不會太高,以適應艱難的環境。同時要保證信息傳遞的質量,所以有三種發布質量模式(QoS)
它原生條件下是基於TCP/IP的的應用層協議屏蔽了消息傳輸的具體數據交互格式。也就是不用關心底層是怎么傳輸的,數據用的是什么格式來傳輸的在物聯網領域(IoT,Internet of Things)未來會有大發展。
MQTT的發展背景
物聯網中的數據傳輸會面臨很多問題,比如在網絡不穩定的情況下,如果保證數據的傳輸沒有問題,如何保證數據不被重復發送,連接斷開后如何進行重連。總體來說,物聯網的接入會面臨以下幾個方面的挑戰:
- 設備、傳感器。物聯網接入對終端采集和控制設備要求高,且終端的改造以及網絡費用成本也比較高。另外,其對終端的能耗要求也比較高。
- 網絡。現有的網絡傳輸貸款參差不齊,傳輸網絡不穩定。
- 服務器。高並發情況下,多客戶端的接入能力以及消息處理能力。
MQTT的發展歷史
在物聯網中,開源和開放標准是基本的要素。MQTT的發展歷史大致如下:
- 1999年,IBM和合作伙伴共同發明了MQTT協議。
- 2004年,org開放了論壇,供大家廣泛參與。
- 2011年,IBM建立了Eclipse開源項目Paho,並貢獻了代碼。Eclipse Paho是MQTT的Java實現版本。
- 2013年,OASIS MQTT技術規范委員會成立。
- 2014年,MQTT正式成為推薦的物聯網傳輸協議標准。
MQTT協議
目前MQTT大家都用在了手機推送,如FacebookMessenger,因為小巧,省電,協議開銷小和能高效的向一和多個接收者傳遞信息,故適用於移動應用設備上。那么輕巧在哪里呢,協議簡單,最小的頭部只需2個字節。相對於XMPP,MQTT更加輕量級,並且占用用戶很少的帶寬。整體上協議可拆分為:固定頭部+可變頭部+消息體
- 第一個byte 用於說明消息體的信息.
- 第二個byte 用於傳輸我們需要傳輸的數據.
- 更多詳情請看協議 msg-format 部分
MessageType(0和15保留,共占4個字節)
- “MQTT_CONNECT”=>1,//請求連接
- “MQTT_CONNACK”=>2,//請求應答
- “MQTT_PUBLISH”=>3,//發布消息
- “MQTT_PUBACK”=>4,//發布應答
- “MQTT_PUBREC”=>5,//發布已接收,保證傳遞1
- “MQTT_PUBREL”=>6,//發布釋放,保證傳遞2
- “MQTT_PUBCOMP”=>7,//發布完成,保證傳遞3
- “MQTT_SUBSCRIBE”=>8,//訂閱請求
- “MQTT_SUBACK”=>9,//訂閱應答
- “MQTT_UNSUBSCRIBE”=>10,//取消訂閱
- “MQTT_UNSUBACK”=>11,//取消訂閱應答
- “MQTT_PINGREQ”=>12,//ping請求
- “MQTT_PINGRESP”=>13,//ping響應
- “MQTT_DISCONNECT”=>14//斷開連接
DUP flag
用來在保證消息傳輸可靠的,如果設置為1,則在下面的變長頭部里多加MessageId,並需要回復確認,保證消息傳輸完成,但不能用於檢測消息重復發送。
Qos
主要用於PUBLISH(發布態)消息的,保證消息傳遞的次數。
- 00表示最多一次 即<=1
- 01表示至少一次 即>=1
- 10表示一次,即==1
- 11保留后用
Retain
主要用於PUBLISH(發布態)的消息,表示服務器要保留這次推送的信息,如果有新的訂閱者出現,就把這消息推送給它。如果不設那么推送至當前訂閱的就釋放了。
固定頭部的byte 2
是用來保存接下去的變長頭部+消息體的總大小的。但可以不直接保存的,同樣也是可以擴展,其機制是前7位用於保存長度,后一部用做標識。
我舉個例了,即如果計算出后面的大小為0<length<=127的,正常保存;如果是127<length<16383的,則需要二個字節保存了,將第一個字節的最大的一位置1,表示未完。然后第二個字節繼續存。
拿130來說,第一個字節存10000011,第二個字節存000000001,也就是0x83,0x01,把兩個字節連起來看,第二個字節權重從2的8次開始。同起可以加第3個字節,最多可以加至第4個字節。故MQTT協議最多可以實現268 435 455 (0xFF, 0xFF, 0xFF, 0x7F)將近256M的數據。可謂能伸能縮。
MQTT的使用
MQTT協議的架構,用一個示例說明。比如有1個溫度傳感器(1個Machine),2個小的顯示屏(2個Machine),顯示屏要顯示溫度傳感器的溫度值。可通過MQTT V3.1 Protocol Specification查閱詳細規范的細節。
顯示器需要先通過MQTT協議subscribe(訂閱)一個比如叫temperature的topic(主題):
當溫度傳感器publish(發布)溫度數據,顯示器就可以收到了:
注:以上兩張圖,取自MQTT and CoAP, IoT Protocols
協議里還有2個主要的角色:
- client,客戶端
- broker,服務器端
它們是通過TCP/IP協議連接的。因為MQTT是協議,所以不能拿來直接用的,就好比HTTP協議一樣。需要找實現這個協議的庫或者服務器來運行。
各種語言的Clients及Brokers/Servers:https://github.com/mqtt/mqtt.github.io/wiki/software?id=software
參考鏈接
https://www.biaodianfu.com/mqtt.html