MQTT V3.1----publish解讀


客戶端/服務器的發布消息行為,與PUBLISH相關的消息類型:

PUBLISH

客戶端發布消息經由服務器分發到所有對應的訂閱者那里。一個訂閱者可以訂閱若干個主題(Topic name),但一個PUBLISH消息只能擁有一個主題。

消息架構一覽:

  Description 7 6 5 4 3 2 1 0
Fixed header/固定頭部
byte 1   Message Type(3) DUP flag QoS level RETAIN
    0 0 1 1 0 0 1 0
byte 2 Remaining Length
Variable header/可變頭部
Topic name
byte 1 Length MSB (0) 0 0 0 0 0 0 0 0
byte 2 Length LSB (3) 0 0 0 0 0 0 1 1
byte 3 'a' (0x61) 0 1 1 0 0 0 0 1
byte 4 '/' (0x2F) 0 0 1 0 1 1 1 1
byte 5 'b' (0x62) 0 1 1 0 0 0 1 0
Message Identifier
byte 6 Message ID MSB (0) 0 0 0 0 0 0 0 0
byte 7 Message ID LSB (10) 0 0 0 0 1 0 1 0
Playload/消息體
BLOB,二進制對象形式。二進制具體包含的內容和格式,可有應用程序自身定義。若消息體為空(0長度)也是可能的。

固定頭部

DUP flag,設為0,表示當前為第一次發送。

RETAIN flag,只有在PUBLISH消息中才有效。

  • 1:表示發送的消息需要一直持久保存,不但要發送給當前的訂閱者,並且以后新來的訂閱了此Topic name的訂閱者會馬上得到推送。 備注:新來乍到的訂閱者,只會取出最新的一個RETAIN flag = 1的消息推送,不是所有。
  • 0:僅僅為當前訂閱者推送此消息。

可變頭部

Topic name,UTF-8編碼字符串形式,不支持通配符!

消息體

一般作為UTF-8編碼寫入接口,但不排除自定義的消息格式。

空的消息體(zero-length)的PUBLISH消息也可以是合法的。

當服務器接收到空消息體(zero-length payload)、retain = 1、具有topic name的一個PUBLISH特殊消息,表示同時滿足retain = 1、相同topic name的這兩個特征的被持久化PUBLISH消息,可被刪除。

Response/響應

固定頭部QoS level決定了消息中間件針對發布者具體需要響應的內容:

QoS Level Expected response
QoS 0 None
QoS 1 PUBACK
QoS 2 PUBREC

備注:僅僅針對發布PUBLISH消息的發布者。

Actions:

無論是訂閱者還是服務器接收到PUBLISH消息之后,需要根據QoS level執行不同動作。

QoS Level Expected Action
QoS 0 發送到所有感興趣者
QoS 1 持久化記錄下來,發送到所有感興趣的參與者,返回一個PUBACK消息給發送者
QoS 2 持久化記錄下來,暫時不發送所有感興趣的參與者,返回一個PUBREC消息給發送者

如果服務器收到PUBLISH消息,參與者指的是訂閱者。如果訂閱者收到PUBLISH消息,參與者就是服務器。 需要注意:

  1. 發布者發布的PUBLISH消息發送到服務器,在payload/消息體處可能夾帶有私貨,可能含有自定義的數據 格式
  2. 若兼容MQTT客戶端,經由服務器分發到所有對應訂閱者處只能是規規矩矩的PUBLISH消息,並且固定頭部的RETAIN標志不能被設置成有效值1

授權

未經授權的發布者提交的PUBLISH消息,服務器會忽略掉,客戶端不會被通知。

PUBACK

作為訂閱者/服務器接收(QoS level = 1)PUBLISH消息之后對發送者的響應,整個消息不復雜。

  Description 7 6 5 4 3 2 1 0
Fixed header/固定頭部
byte 1   Message type (4) DUP flag QoS flags RETAIN
    0 1 0 0 x x x x
byte 2   Remaining Length (2)
    0 0 0 0 0 0 1 0
Variable header/可變頭部
Message Identifier
byte 1 Message ID MSB (0) 0 0 0 0 0 0 0 0
byte 2 Message ID LSB (10) 0 0 0 0 1 0 1 0

雖沒有消息體,但可變頭部附加一個16位的無符號short類型。

PUBREC

字面意思為Assured publish received,作為訂閱者/服務器對QoS level = 2的發布PUBLISH消息的發送方的響應,確認已經收到,為QoS level = 2消息流的第二個消息。 和PUBACK相比,除了消息類型不同外,其它都是一樣。

  Description 7 6 5 4 3 2 1 0
Fixed header/固定頭部
byte 1   Message type (5) DUP flag QoS flags RETAIN
    0 1 0 1 x x x x
byte 2   Remaining Length (2)
    0 0 0 0 0 0 1 0
Variable header/可變頭部
Message Identifier
byte 1 Message ID MSB (0) 0 0 0 0 0 0 0 0
byte 2 Message ID LSB (10) 0 0 0 0 1 0 1 0

無論是訂閱者還是服務器,在消費PUBREC消息之后需要發送一個PUBREL消息給發送者(和PUBREC具有同樣的消息ID),確認已收到。

PUBREL

Qos level = 2的協議流的第三個消息,有PUBLISH消息的發布者發送,參與方接收。完整示范如下:

  Description 7 6 5 4 3 2 1 0
Fixed header/固定頭部
byte 1   Message type (6) DUP flag QoS flags RETAIN
    0 1 1 0 0 0 1 x
byte 2   Remaining Length (2)
    0 0 0 0 0 0 1 0
Variable header/可變頭部
Message Identifier
byte 1 Message ID MSB (0) 0 0 0 0 0 0 0 0
byte 2 Message ID LSB (10) 0 0 0 0 1 0 1 0

QoS level 1,PUBREL消息要求如此。

DUP flag 為0,表示消息第一次被發送。

毫無疑問,剩余長度為2個byte長度。

可變頭部中,消息ID和發布者接收到的PUBREC所包含的消息ID是一致的。

動作:

  1. 服務器接收到發布者(a)的PUBREL消息,此時服務器讓發布者(a)剛才發布PUBLISH消息可用,發送此PUBLISH消息給所有訂閱此主題的訂閱者,然后發送PUBCOMP消息給發布者(a)
  2. 可變頭部包含消息ID和服務器接收的PUBREL消息ID是一致的。 一個訂閱者接收到PUBREL消息,訂閱者使PUBLISH消息可用,然后反饋一個PUBCOMP消息給服務器

PUBCOMP

作為QoS level = 2消息流第四個,也是最后一個消息,由收到PUBREL的一方向另一方做出的響應消息。

完整的消息一覽,和PUBREL一致,除了消息類型。

  Description 7 6 5 4 3 2 1 0
Fixed header/固定頭部
byte 1   Message type (7) DUP flag QoS flags RETAIN
    0 1 1 1 x x x x
byte 2   Remaining Length (2)
    0 0 0 0 0 0 1 0
Variable header/可變頭部
Message Identifier
byte 1 Message ID MSB (0) 0 0 0 0 0 0 0 0
byte 2 Message ID LSB (10) 0 0 0 0 1 0 1 0

當客戶端接收一個PUBCOMP消息時,客戶端摒棄原來的消息,因為它已經成功發送消息到服務器。

小結

消息的發布和確認等一些流程,主要是跟消息發布者所設定的QoS level有關;稍加整理,繪制了下面一張圖,理解起來可能會更清晰些:

Publish流程圖

上圖針對的是客戶端發布消息到服務器端的方向。

為了確保消息已經成功傳遞過去,只有收到了確認,才會讓人特別放心。

在QoS level = 2時,通信雙方都需要知道各自的確認流程以及所處階段等,交互很多,數據量大的情況下,可能會造成數據線路傳遞擁塞。服務器選擇QoS = 0/1,大部分情況都是可以應對的。 比如重要消息,就要確保對方都要收到,然后彼此確認,OK,這個消息是真實、有效的。

無論Qos level為0、1,還是2,服務器(具備所有條件都滿足之后)總要把收到的具體內容和topic組裝成一個新的PUBLISH Message(也不一定要重新構造,但要求推送的PUBLISH消息,一定要具有明確的主題和內容,RETAIN標志不能設置為1)推送到所有感興趣的訂閱者。

嗯,消息的發布來源別忘記還有可能來自CONNECT消息中的Will Topic和Will Message,若是設置了Will flag標記的話。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM