前言
記憶不太好的時候,只能翻看以前的文章/筆記重新溫習一遍,但找不到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 |