MQTT協(xié)議之頭部信息介紹

前言

MQTT(Message Queue Telemetry Transport),遙測傳輸協(xié)議,提供訂閱/發(fā)布模式,更為簡約、輕量,易于使用,針對受限環(huán)境(帶寬低、網(wǎng)絡(luò)延遲高、網(wǎng)絡(luò)通信不穩(wěn)定),可以簡單概括為物聯(lián)網(wǎng)打造,官方總結(jié)特點(diǎn)如下:

1.使用發(fā)布/訂閱消息模式,提供一對多的消息發(fā)布,解除應(yīng)用程序耦合。
2. 對負(fù)載內(nèi)容屏蔽的消息傳輸。
3. 使用 TCP/IP 提供網(wǎng)絡(luò)連接。
4. 有三種消息發(fā)布服務(wù)質(zhì)量:
    “至多一次”,消息發(fā)布完全依賴底層 TCP/IP 網(wǎng)絡(luò)。會發(fā)生消息丟失或重復(fù)。這一級別可用于如下情況,環(huán)境傳感器數(shù)據(jù),丟失一次讀記錄無所謂,因?yàn)椴痪煤筮€會有第二次發(fā)送。
    “至少一次”,確保消息到達(dá),但消息重復(fù)可能會發(fā)生。
    “只有一次”,確保消息到達(dá)一次。這一級別可用于如下情況,在計費(fèi)系統(tǒng)中,消息重復(fù)或丟失會導(dǎo)致不正確的結(jié)果。
5. 小型傳輸,開銷很小(固定長度的頭部是 2 字節(jié)),協(xié)議交換最小化,以降低網(wǎng)絡(luò)流量。
6. 使用 Last Will 和 Testament 特性通知有關(guān)各方客戶端異常中斷的機(jī)制。

在沉寂了四年之后, MQTT 3.1.1規(guī)范 于2014年10月30號正式發(fā)布,與此同時MQTT 3.1.1已成為OASIS(結(jié)構(gòu)化信息標(biāo)準(zhǔn)促進(jìn)組織)開放物聯(lián)網(wǎng)消息傳遞協(xié)議標(biāo)準(zhǔn)( 連接1 連接2 ),換種說法就是MQTT 3.1.1已升級為國際物聯(lián)網(wǎng)標(biāo)準(zhǔn)。
  細(xì)心的朋友一定會發(fā)現(xiàn),原來MQTT 3.1規(guī)范是IBM的協(xié)議,到了MQTT 3.1.1規(guī)范 后就變成了OASIS的標(biāo)準(zhǔn)。
  中文版的文檔查看以下的鏈接:
  MQTT協(xié)議v3.1中文版
  MQTT協(xié)議v3.1.1中文版

協(xié)議介紹

固定頭部

固定頭部,使用兩個字節(jié),共16位:

mqtt 固定頭部

Byte 1 消息類型和標(biāo)志字段,消息類型(4-7),使用4位二進(jìn)制表示,可代表16種消息類型。
Byte 2 剩余長度字段(至少1個字節(jié),最多4個字節(jié)),采用big-endian模式存儲。

消息類型

mqtt 消息類型

除去0和15位置屬于保留待用,共14種消息事件類型。

DUP flag(打開標(biāo)志)

保證消息可靠傳輸,默認(rèn)為0,只占用一個字節(jié),表示第一次發(fā)送。不能用于檢測消息重復(fù)發(fā)送等。只適用于客戶端或服務(wù)器端嘗試重發(fā)PUBLISH, PUBREL, SUBSCRIBE 或 UNSUBSCRIBE消息,注意需要滿足以下條件:

 當(dāng) QoS > 0
 消息需要回復(fù)確認(rèn)

此時,在可變頭部需要包含消息ID。當(dāng)值為1時,表示當(dāng)前消息先前已經(jīng)被傳送過。

QoS(Quality of Service,服務(wù)質(zhì)量)

使用兩個二進(jìn)制表示PUBLISH類型消息:

mqtt 服務(wù)質(zhì)量

RETAIN(保持)

僅針對PUBLISH消息。不同值,不同含義:
  1:表示發(fā)送的消息需要一直持久保存(不受服務(wù)器重啟影響),不但要發(fā)送給當(dāng)前的訂閱者,并且以后新來的訂閱了此Topic name的訂閱者會馬上得到推送。

備注:新來乍到的訂閱者,只會取出最新的一個RETAIN flag = 1的消息推送。

0:僅僅為當(dāng)前訂閱者推送此消息。
假如服務(wù)器收到一個空消息體(zero-length payload)、RETAIN = 1、已存在Topic name的PUBLISH消息,服務(wù)器可以刪除掉對應(yīng)的已被持久化的PUBLISH消息。

Remaining Length(剩余長度)

在當(dāng)前消息中剩余的byte(字節(jié))數(shù),包含可變頭部和負(fù)荷(稱之為內(nèi)容/body,更為合適)。單個字節(jié)最大值:01111111,16進(jìn)制:0x7F,10進(jìn)制為127。單個字節(jié)為什么不能是11111111(0xFF)呢?因?yàn)镸QTT協(xié)議規(guī)定,第八位(最高位)若為1,則表示還有后續(xù)字節(jié)存在。
  同時MQTT協(xié)議最多允許4個字節(jié)表示剩余長度。那么最大長度為:0xFF,0xFF,0xFF,0x7F。
二進(jìn)制表示為:11111111,11111111,11111111,01111111
十進(jìn)制:268435455 byte=261120KB=256MB=0.25GB
四個字節(jié)之間值的范圍:

mqtt 剩余長度

可變頭部

固定頭部僅定義了消息類型和一些標(biāo)志位,一些消息的元數(shù)據(jù),需要放入可變頭部中。可變頭部內(nèi)容字節(jié)長度 + Payload/負(fù)荷字節(jié)長度 = 剩余長度,這個是需要牢記的。可變頭部,包含了協(xié)議名稱,版本號,連接標(biāo)志,用戶授權(quán),心跳時間等內(nèi)容,這部分和后面要講到的CONNECT消息類型,有重復(fù),暫時略過。

Payload/消息體/負(fù)荷

消息體主要是為配合固定/可變頭部命令(比如CONNECT可變頭部User name標(biāo)記若為1則需要在消息體中附加用戶名稱字符串)而存在。
  CONNECT/SUBSCRIBE/SUBACK/PUBLISH等消息有消息體。PUBLISH的消息體以二進(jìn)制形式對待。
  請記住MQTT協(xié)議只允許在PUBLISH類型消息體中使用自定義特性,在固定/可變頭部想加入自定義私有特性,就免了吧。這也是為了協(xié)議免于流于形式,變得很分裂也為了兼顧現(xiàn)有客戶端等。比如支持壓縮等,那就可以在Payload中定義數(shù)據(jù)支持,在應(yīng)用中進(jìn)行讀取處理。這部分會在后面的文章中詳細(xì)論述。

消息標(biāo)識符/消息ID

固定頭中的QoS level標(biāo)志值為1或2時才會在:PUBLISH,PUBACK,PUBREC,PUBREL,PUBCOMP,SUBSCRIBE,SUBACK,UNSUBSCRIBE,UNSUBACK等消息的可變頭中出現(xiàn)。
  一個16位無符號位的short類型值(值不能為 0,0做保留作為無效的消息ID),僅僅要求在一個特定方向(服務(wù)器發(fā)往客戶端為一個方向,客戶端發(fā)送到服務(wù)器端為另一個方向)的通信消息中必須唯一。比如客戶端發(fā)往服務(wù)器,有可能存在服務(wù)器發(fā)往客戶端會同時存在重復(fù),但不礙事。
  可變頭部中,需要兩個字節(jié)的順序是MSB(Most Significant Bit) LSB(Last/Least Significant Bit),翻譯成中文就是,最高有效位,最低有效位。最高有效位在最低有效位左邊/上面,表示這是一個大端字節(jié)/網(wǎng)絡(luò)字節(jié)序,符合人的閱讀習(xí)慣,高位在最左邊。

mqtt 消息標(biāo)識符

小結(jié)

掌握固定頭部的QoS level、RETAIN標(biāo)記、可變頭部的Connect flags作用和意義,對總體理解MQTT作用很大。下面列舉了一些常用的操作:
CONNECT
  TCP連接建立完畢后,Client向Server發(fā)出一個Request。
如果一段時間內(nèi)接收不到Server的Response,則關(guān)閉socket,重新建立一個session連接。
  如果一個ClientID已經(jīng)與服務(wù)器連接,則持有同樣ClientID的舊有連接必須由服務(wù)器關(guān)閉后,新建立才能建立。
CONNACK
  Server發(fā)出Response響應(yīng)。

0x00 Connection Accepted
0x01 Connection Refused: unacceptable protocol version
0x02 Connection Refused: identifier rejected
0x03 Connection Refused: server unavailable
0x04 Connection Refused: bad user name or password
0x05 Connection Refused: not authorized 

PUBLISH 發(fā)布消息
  Client/Servier均可以進(jìn)行PUBLISH。
  publish message 應(yīng)該包含一個TopicName(Subject/Channel),即訂閱關(guān)鍵詞。

關(guān)于Topic通配符

  • /:用來表示層次,比如a/b,a/b/c。
  • #:表示匹配>=0個層次,比如a/#就匹配a/,a/b,a/b/c。
    單獨(dú)的一個#表示匹配所有。不允許 a#和a/#/c。
  • +:表示匹配一個層次,例如a/+匹配a/b,a/c,不匹配a/b/c。
    單獨(dú)的一個+是允許的,a+不允許,a/+/b不允許

PUBACK 發(fā)布消息后的確認(rèn)
  QoS=1時,Server向Client發(fā)布該確認(rèn)(Client收到確認(rèn)后刪除),訂閱者向Server發(fā)布確認(rèn)。
PUBREC / PUBREL / PUBCOMP
  QoS=2時
  1. Server->Client發(fā)布PUBREC(已收到);
  2. Client->Server發(fā)布PUBREL(已釋放);
  3. Server->Client發(fā)布PUBCOMP(已完成),Client刪除msg;訂閱者也會向Server發(fā)布類似過程確認(rèn)。
PINGREQ / PINGRES 心跳
  Client有責(zé)任發(fā)送KeepAliveTime時長告訴給Server。在一個時長內(nèi),發(fā)送PINGREQ,Server發(fā)送PINGRES確認(rèn)。
  Server在1.5個時長內(nèi)未收到PINGREQ,就斷開連接。
  Client在1個時長內(nèi)未收到PINGRES,斷開連接。
  一般來說,時長設(shè)置為幾個分鐘。最大18小時,0表示一直未斷開。
Clean Session
  如果為false(flag=0),Client斷開連接后,Server應(yīng)該保存Client的訂閱信息。
  如果為true(flag=1),表示Server應(yīng)該立刻丟棄任何會話狀態(tài)信息。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,527評論 6 544
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,687評論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,640評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,957評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,682評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 56,011評論 1 329
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,009評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,183評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,714評論 1 336
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,435評論 3 359
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,665評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,148評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,838評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,251評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,588評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,379評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,627評論 2 380

推薦閱讀更多精彩內(nèi)容