MQTT協(xié)議,終于有人講清楚了
-
mqtt協(xié)議
-
1 MQTT協(xié)議特點
-
發(fā)布和訂閱
-
QoS(Quality of Service levels)
-
2 MQTT 數(shù)據(jù)包結(jié)構(gòu)
-
2.1 MQTT固定頭
-
2.2 MQTT可變頭 / Variable header
-
2.3 Payload消息體
-
3 環(huán)境搭建
-
3.1 MQTT服務(wù)器搭建
-
3.2 MQTT Client
-
4 總結(jié)
mqtt協(xié)議
MQTT(Message Queuing Telemetry Transport,消息隊列遙測傳輸協(xié)議),是一種基于發(fā)布/訂閱(publish/subscribe)模式的“輕量級”通訊協(xié)議,該協(xié)議構(gòu)建于TCP/IP協(xié)議上,由IBM在1999年發(fā)布。
MQTT最大優(yōu)點在于,用極少的代碼和有限的帶寬,為連接遠程設(shè)備提供實時可靠的消息服務(wù)。
作為一種低開銷、低帶寬占用的即時通訊協(xié)議,使其在物聯(lián)網(wǎng)、小型設(shè)備、移動應(yīng)用等方面有較廣泛的應(yīng)用。
1 MQTT協(xié)議特點
MQTT是一個基于客戶端-服務(wù)器的消息發(fā)布/訂閱傳輸協(xié)議。
MQTT協(xié)議是輕量、簡單、開放和易于實現(xiàn)的,這些特點使它適用范圍非常廣泛。在很多情況下,包括受限的環(huán)境中,如:機器與機器(M2M)通信和物聯(lián)網(wǎng)(IoT)。
其在,通過衛(wèi)星鏈路通信傳感器、偶爾撥號的醫(yī)療設(shè)備、智能家居、及一些小型化設(shè)備中已廣泛使用。
MQTT協(xié)議當前版本為,2014年發(fā)布的MQTT v3.1.1。除標準版外,還有一個簡化版MQTT-SN,該協(xié)議主要針對嵌入式設(shè)備,這些設(shè)備一般工作于TCP/IP網(wǎng)絡(luò),如:ZigBee。
MQTT 與 HTTP 一樣,MQTT 運行在傳輸控制協(xié)議/互聯(lián)網(wǎng)協(xié)議 (TCP/IP) 堆棧之上。
MQTT OSI
發(fā)布和訂閱
MQTT使用的發(fā)布/訂閱消息模式,它提供了一對多的消息分發(fā)機制,從而實現(xiàn)與應(yīng)用程序的解耦。
這是一種消息傳遞模式,消息不是直接從發(fā)送器發(fā)送到接收器(即點對點),而是由MQTT server(或稱為 MQTT Broker)分發(fā)的。
MQTT 服務(wù)器是發(fā)布-訂閱架構(gòu)的核心。
它可以非常簡單地在Raspberry Pi或NAS等單板計算機上實現(xiàn),當然也可以在大型機或 Internet 服務(wù)器上實現(xiàn)。
服務(wù)器分發(fā)消息,因此必須是發(fā)布者,但絕不是訂閱者!
客戶端可以發(fā)布消息(發(fā)送方)、訂閱消息(接收方)或兩者兼而有之。
客戶端(也稱為節(jié)點)是一種智能設(shè)備,如微控制器或具有 TCP/IP 堆棧和實現(xiàn) MQTT 協(xié)議的軟件的計算機。
消息在允許過濾的主題下發(fā)布。主題是分層劃分的 UTF-8 字符串。不同的主題級別用斜杠/作為分隔符號。
我們來看看下面的設(shè)置。
-
光伏發(fā)電站是發(fā)布者(
Publisher)。
-
主要主題(Topic)級別是"PV",這個工廠發(fā)布兩個子級別"sunshine"和"data";
-
"PV/sunshine"是一個布爾值(true/fault,也可以是 1/0),充電站需要它來知道是否應(yīng)該裝載電動汽車(僅在陽光普照時 :))。
-
充電站(EVSE)是訂閱者,訂閱"PV/sunshine"從服務(wù)器獲取信息。
-
"PV/data"另一方面,以 kW 為單位傳輸工廠產(chǎn)生的瞬時功率,并且該主題可以例如通過計算機或平板電腦訂閱,以生成一天內(nèi)傳輸功率的圖表。
這就是一個簡單的MQTT的應(yīng)用場景,具體如下圖所示;
MQTT 發(fā)布和訂閱
QoS(Quality of Service levels)
服務(wù)質(zhì)量是 MQTT 的一個重要特性。當我們使用 TCP/IP 時,連接已經(jīng)在一定程度上受到保護。但是在無線網(wǎng)絡(luò)中,中斷和干擾很頻繁,MQTT 在這里幫助避免信息丟失及其服務(wù)質(zhì)量水平。這些級別在發(fā)布時使用。如果客戶端發(fā)布到 MQTT 服務(wù)器,則客戶端將是發(fā)送者,MQTT 服務(wù)器將是接收者。當MQTT服務(wù)器向客戶端發(fā)布消息時,服務(wù)器是發(fā)送者,客戶端是接收者。
QoS 0
這一級別會發(fā)生消息丟失或重復(fù),消息發(fā)布依賴于底層TCP/IP網(wǎng)絡(luò)。即:<=1
QoS 1
QoS 1 承諾消息將至少傳送一次給訂閱者。
QoS 2
使用 QoS 2,我們保證消息僅傳送到目的地一次。為此,帶有唯一消息 ID 的消息會存儲兩次,首先來自發(fā)送者,然后是接收者。QoS 級別 2 在網(wǎng)絡(luò)中具有最高的開銷,因為在發(fā)送方和接收方之間需要兩個流。
2 MQTT 數(shù)據(jù)包結(jié)構(gòu)
-
固定頭(Fixed header),存在于所有MQTT數(shù)據(jù)包中,表示數(shù)據(jù)包類型及數(shù)據(jù)包的分組類標識;
-
可變頭(Variable header),存在于部分MQTT數(shù)據(jù)包中,數(shù)據(jù)包類型決定了可變頭是否存在及其具體內(nèi)容;
-
消息體(Payload),存在于部分MQTT數(shù)據(jù)包中,表示客戶端收到的具體內(nèi)容;
整體MQTT的消息格式如下圖所示;
2.1MQTT固定頭
固定頭存在于所有MQTT數(shù)據(jù)包中,其結(jié)構(gòu)如下:
下面簡單分析一下固定頭的消息格式;
MQTT消息類型 / message type
**位置:**byte 1, bits 7-4。
4位的無符號值,類型如下:
名稱
值
流方向
描述
Reserved
0
不可用
保留位
CONNECT
1
客戶端到服務(wù)器
客戶端請求連接到服務(wù)器
CONNACK
2
服務(wù)器到客戶端
連接確認
PUBLISH
3
雙向
發(fā)布消息
PUBACK
4
雙向
發(fā)布確認
PUBREC
5
雙向
發(fā)布收到(保證第1部分到達)
PUBREL
6
雙向
發(fā)布釋放(保證第2部分到達)
PUBCOMP
7
雙向
發(fā)布完成(保證第3部分到達)
SUBSCRIBE
8
客戶端到服務(wù)器
客戶端請求訂閱
SUBACK
9
服務(wù)器到客戶端
訂閱確認
UNSUBSCRIBE
10
客戶端到服務(wù)器
請求取消訂閱
UNSUBACK
11
服務(wù)器到客戶端
取消訂閱確認
PINGREQ
12
客戶端到服務(wù)器
PING請求
PINGRESP
13
服務(wù)器到客戶端
PING應(yīng)答
DISCONNECT
14
客戶端到服務(wù)器
中斷連接
Reserved
15
不可用
保留位
標識位 / DUP
**位置:**byte 1, bits 3-0。
在不使用標識位的消息類型中,標識位被作為保留位。如果收到無效的標志時,接收端必須關(guān)閉網(wǎng)絡(luò)連接:
數(shù)據(jù)包
標識位
Bit 3
Bit 2
Bit 1
Bit 0
CONNECT
保留位
0
0
0
0
CONNACK
保留位
0
0
0
0
PUBLISH
MQTT 3.1.1使用
DUP1
QoS2
QoS2
RETAIN3
PUBACK
保留位
0
0
0
0
PUBREC
保留位
0
0
0
0
PUBREL
保留位
0
0
0
0
PUBCOMP
保留位
0
0
0
0
SUBSCRIBE
保留位
0
0
0
0
SUBACK
保留位
0
0
0
0
UNSUBSCRIBE
保留位
0
0
0
0
UNSUBACK
保留位
0
0
0
0
PINGREQ
保留位
0
0
0
0
PINGRESP
保留位
0
0
0
0
DISCONNECT
保留位
0
0
0
0
-
DUP:發(fā)布消息的副本。用來在保證消息的可靠傳輸,如果設(shè)置為 1,則在下面的變長中增加MessageId,并且需要回復(fù)確認,以保證消息傳輸完成,但不能用于檢測消息重復(fù)發(fā)送。
-
QoS發(fā)布消息的服務(wù)質(zhì)量(前面已經(jīng)做過介紹),即:保證消息傳遞的次數(shù)
-
00:最多一次,即:<=1
-
01:至少一次,即:>=1
-
10:一次,即:=1
-
11:預(yù)留
-
RETAIN:發(fā)布保留標識,表示服務(wù)器要保留這次推送的信息,如果有新的訂閱者出現(xiàn),就把這消息推送給它,如果設(shè)有那么推送至當前訂閱者后釋放。
剩余長度(Remaining Length)
位置:byte 1。
固定頭的第二字節(jié)用來保存變長頭部和消息體的總大小的,但不是直接保存的。這一字節(jié)是可以擴展,其保存機制,前7位用于保存長度,后一部用做標識。當最后一位為 1時,表示長度不足,需要使用二個字節(jié)繼續(xù)保存。例如:計算出后面的大小為0
2.2MQTT可變頭 / Variable header
MQTT數(shù)據(jù)包中包含一個可變頭,它駐位于固定的頭和負載之間??勺冾^的內(nèi)容因數(shù)據(jù)包類型而不同,較常的應(yīng)用是做為包的標識:
Bit
7 — 0
byte 1
包標簽符(MSB)
byte 2…
包標簽符(LSB)
很多類型數(shù)據(jù)包中都包括一個2字節(jié)的數(shù)據(jù)包標識字段,這些類型的包有:
PUBLISH (QoS > 0)、PUBACK、PUBREC、PUBREL、PUBCOMP、
SUBSCRIBE、SUBACK、UNSUBSCRIBE、UNSUBACK
2.3Payload消息體
Payload消息體是MQTT數(shù)據(jù)包的第三部分,CONNECT、SUBSCRIBE、SUBACK、UNSUBSCRIBE四種類型的消息 有消息體:
-
CONNECT,消息體內(nèi)容主要是:客戶端的ClientID、訂閱的Topic、Message以及用戶名和密碼
-
SUBSCRIBE,消息體內(nèi)容是一系列的要訂閱的主題以及QoS。
-
SUBACK,消息體內(nèi)容是服務(wù)器對于SUBSCRIBE所申請的主題及QoS進行確認和回復(fù)。
-
UNSUBSCRIBE,消息體內(nèi)容是要訂閱的主題。
3 環(huán)境搭建
介紹完基礎(chǔ)理論部分,下面在Windows平臺上搭建一個簡單的MQTT應(yīng)用,進行簡單的應(yīng)用,整體架構(gòu)如下圖所示;
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-ScRucIVO-1625480723109)(架構(gòu)圖.png)]
3.1 MQTT服務(wù)器搭建
目前MQTT代理的主流平臺有下面幾個:
-
Mosquitto:https://mosquitto.org/
-
VerneMQ:https://vernemq.com/
-
EMQTT:http://emqtt.io/
本文將使用 Mosquitoo 進行測試,進入到安裝頁面,下載自己電腦的系統(tǒng)所適配的程序;
下載頁面安裝成功之后,進入到安裝路徑下,找到mosquitto.exe;
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-YXZupgOv-1625480723111)(image-20210705171401654.png)]
按住Shift,右鍵鼠標點擊空白處,然后打開Powershell,正常打開一個終端軟件即可;
-
輸入
./mosquitto.exe -h可以查看相應(yīng)的幫助;
-
輸入./mosquitto.exe -p 10086,就開啟了MQTT服務(wù),監(jiān)聽的地址是127.0.0.1,端口是10086;
具體如下圖所示;
3.2 MQTT Client
服務(wù)器搭建好了,下面就是開啟客戶端,進行發(fā)布和訂閱,這樣就可以傳輸相應(yīng)的消息。
這里我使用的是自己編譯了一個QT mqtt client程序,是基于Qt的官方庫進行編譯的,下面打開這個軟件,下一期簡單介紹一下如何完成這個客戶端,并設(shè)置好相應(yīng)參數(shù):
-
地址:
127.0.0.1
-
端口:10086
然后訂閱主題,就可以互相發(fā)送數(shù)據(jù)了,具體如下圖所示;
結(jié)合前面的圖片來看,整體的架構(gòu)如下所示;
4 總結(jié)
本文簡單介紹了MQTT協(xié)議的工作原理,以及相應(yīng)的協(xié)議格式,簡單介紹了協(xié)議的一些細節(jié),具體舉出了相應(yīng)的應(yīng)用場景,作者水平和能力有限,文中難免存在錯誤和紕漏,請大佬不吝賜教。
本期就到此結(jié)束了,我是小麥,我們下期再見。