MQTT協議筆記之訂閱
前言
記憶不太好的時候,只能翻看以前的文章/筆記重新溫習一遍,但找不到MQTT協議有關訂閱部分的描述,好不容易從Evernote中找到貼出來,這樣整個MQTT協議筆記,就比較齊全了。
SUBSCRIBE
一般來講,客戶端在成功建立TCP連接之后,發送CONNECT消息,在得到服務器端授權允許建立彼此連接的CONNACK消息之后,客戶端會發送SUBSCRIBE消息,訂閱感興趣的Topic主題列表(至少一個主題),一個完整示范如下:
Description | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | ||
---|---|---|---|---|---|---|---|---|---|---|
Fixed header/固定頭部 | ||||||||||
byte 1 | Message Type(8) | DUP flag | QoS level | RETAIN | ||||||
1 | 0 | 0 | 0 | 0 | 0 | 1 | x | |||
byte 2 | Remaining Length | |||||||||
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 | |
Playload/消息體 | ||||||||||
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 | |
Requested QoS | ||||||||||
byte 6 | Requested QoS (1) | x | x | x | x | x | x | 0 | 1 | |
Topic Name | ||||||||||
byte 7 | Length MSB (0) | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | |
byte 8 | Length LSB (3) | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | |
byte 9 | 'c' (0x63) | 0 | 1 | 1 | 0 | 0 | 0 | 1 | 1 | |
byte 10 | '/' (0x2F) | 0 | 0 | 1 | 0 | 1 | 1 | 1 | 1 | |
byte 11 | 'd' (0x64) | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 0 | |
Requested QoS | ||||||||||
byte 12 | Requested QoS (2) | x | x | x | x | x | x | 1 | 0 |
固定頭部
Qos Level,可根據實際情況進行調整為0/1/2等。一般設為0表示最多一次。客戶端可設置OoS Level值。 DUP flag,值為0表示第一次發送。
可變頭部
因為上面示范QoS level值為1,因此需要客戶端傳遞消息ID,16位,無符號的short類型。
消息體
訂閱的主題名稱采用修改版UTF-8編碼,然后緊跟著對應的QoS值。下面的次序,可能更為形象:
Topic name | "a/b" |
Requested QoS | 1 |
Topic name | "c/d" |
Requested QoS | 2 |
訂閱者的Topic name支持通配符#和+ :
- #支持一個主題內任意級別話題
- +只匹配一個主題級別的通配符
eg:
finance/stock/#
finance/sotkc/ibm/+
都是有效,更具體規則,請參閱協議附加部分。
在服務器接收處理時,按照順序讀取即可:
String topicName = readUTF();
int qosVal = read();
服務器可以發送QoS不大于客戶端設置OoS的消息,尤其是服務器不提供良好的持久化機制的時候。
SUBACK
服務器會對發出SUBSCRIBE的消息返回一個確認消息。
Description | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
---|---|---|---|---|---|---|---|---|---|
Fixed header/固定頭部 | |||||||||
byte 1 | Message type (9) | DUP flag | QoS flags | RETAIN | |||||
1 | 0 | 0 | 1 | x | x | x | x | ||
byte 2 | Remaining Length | ||||||||
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 |
Playload/消息體 | |||||||||
byte 1 | Granted QoS (0) | x | x | x | x | x | x | 0 | 0 |
byte 1 | Granted QoS (2) | x | x | x | x | x | x | 1 | 0 |
可變頭部
Message Identifier,服務器需要附加,客戶端需要處理。
消息體
QoS,為服務器根據實際情況授予的QoS級別列表,和客戶端發送的SUBSCRIBE的訂閱Topic Name順序完全一致。
客戶端訂閱幾個TOPIC,服務器端一一給出各個TOPIC的QoS具體值。
UNSUBSCRIBE
服務器需要支持客戶端取消訂閱功能,UNSUBSCRIBE消息格式和SUBSCRIBE消息格式差不多,除了消息類型不同,消息體中沒有了QoS字節,其它沒有區別。
Description | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | ||
---|---|---|---|---|---|---|---|---|---|---|
Fixed header/固定頭部 | ||||||||||
byte 1 | Message Type(10) | DUP flag | QoS level | RETAIN | ||||||
1 | 0 | 1 | 0 | 0 | 0 | 1 | x | |||
byte 2 | Remaining Length | |||||||||
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 | |
Playload/消息體 | ||||||||||
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 | |
Topic Name | ||||||||||
byte 6 | Length MSB (0) | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | |
byte 7 | Length LSB (3) | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | |
byte 8 | 'c' (0x63) | 0 | 1 | 1 | 0 | 0 | 0 | 1 | 1 | |
byte 9 | '/' (0x2F) | 0 | 0 | 1 | 0 | 1 | 1 | 1 | 1 | |
byte 10 | 'd' (0x64) | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 0 |
可變頭部的消息ID的出現還是由固定頭部的QoS Level(1)決定是否存在。
一般來講,客戶端發布退訂,服務器端需要返回退訂確認。
MQTT沒講是否允許客戶端退訂所有TOPIC。
UNSUBACK
服務器返回的UNSUBSCRIBE消息UNSUBACK相應很簡單,沒有消息體。
Description | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
---|---|---|---|---|---|---|---|---|---|
Fixed header/固定頭部 | |||||||||
byte 1 | Message type (9) | DUP flag | QoS flags | RETAIN | |||||
1 | 0 | 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 |
小結
訂閱部分,共有四個消息,分別一一對應。
命令 | 響應 | 備注 | 建議 |
---|---|---|---|
SUBSCRIBE | SUBACK | 協議沒有涉及最多運行訂閱TOPIC數目,隱藏的隱患 | 建議至多10個 |
UNSUBSCRIBE | UNSUBACK | 是否可以退訂所有訂閱,不詳 | 建議保留至少一個Topic |
posted on 2014-04-12 16:03 nieyong 閱讀(19910) 評論(16) 編輯 收藏 所屬分類: MQTT