前言
记忆不太好的时候,只能翻看以前的文章/笔记重新温习一遍,但找不到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 |