目录
5.1 SUBSCRIBE - 订阅主题报文
客户端向服务端发送SUBSCRIBE报文用于创建一个或多个订阅。每个订阅注册客户端关心的一个或多个主题。为了将应用消息转发给那些订阅匹配的主题,服务端发送PUBLISH报文给客户端。SUBSCRIBE报文也(为每个订阅)指定了最大的QoS等级,服务端根据这个发送应用消息给客户端。
5.1.1 固定报头
Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 | |
---|---|---|---|---|---|---|---|---|
byte 1 | MQTT 报文的类型(8 - SUBSCRIBE) | Reserved 保留位 | ||||||
8,0x8 - SUBSCRIBE | 0 | 0 | 1 | 0 | ||||
byte 2~4 | 剩余长度 | |||||||
SUBSCRIBE控制报固定报头的第3,2,1,0位是保留位,必须分别设置为0,0,1,0。服务端必须将其它的任何值都当做是不合法的并关闭网络连接。
剩余长度字段:等于SUBSCRIBE可变报头的长度(2字节)加上有效载荷的长度。
5.1.2 可变报头
可变报头包含客户端报文标识符。
报文标识符相当于自定义的Topic的ID,用ID号去代替具体的Topic,而不是字段,使得区分发来的Topic的同时又可以节省流量,可自定义,建议自己预先拟定一个服务ID表。
订阅返回,返回Topic订阅成功信息,返回的不是具体Topic,返回的就是报文标识符。
byte 1 | 报文标识符 MSB |
---|---|
byte 2 | 报文标识符 LSB |
5.1.3 有效载荷
SUBSCRIBE报文的有效载荷包含了一个主题过滤器列表,它们表示客户端想要订阅的主题。SUBSCRIBE报文有效载荷中的主题过滤器列表必须是UTF-8字符串。服务端应该支持包含通配符的主题过滤器。如果服务端选择不支持包含通配符的主题过滤器,必须拒绝任何包含通配符过滤器的订阅请求。每一个过滤器后面跟着一个字节,这个字节被叫做 服务质量要求(Requested QoS)。它给出了服务端向客户端发送应用消息所允许的最大QoS等级。
SUBSCRIBE报文的有效载荷必须包含至少一对主题过滤器 和 QoS等级字段组合。没有有效载荷的SUBSCRIBE报文是违反协议的。
byte 1 | Topic长度 MSB |
---|---|
byte 2 | Topic长度 LSB |
byte 3...N | 主题过滤器(Topic Filter) |
byte N+1 | 服务质量要求(Requested QoS) |
byte N+2 | Topic长度 MSB |
byte N+3 | Topic长度 LSB |
byte N+4...X | 主题过滤器(Topic Filter) |
byte X+1 | 服务质量要求(Requested QoS) |
... ... | ... ... |
当前版本的协议没有用到服务质量要求(Requested QoS)字节的高六位。如果有效载荷中的任何位是非零值,或者QoS不等于0,1或2,服务端必须认为SUBSCRIBE报文是不合法的并关闭网络连接。
响应:服务端收到客户端发送的一个SUBSCRIBE报文时,必须使用SUBACK报文响应。
服务端发送给客户端的SUBACK报文对每一对主题过滤器 和QoS等级都必须包含一个返回码。这个返回码必须表示那个订阅被授予的最大QoS等级,或者表示这个订阅失败。服务端可以授予比订阅者要求的低一些的QoS等级。为响应订阅而发出的消息的有效载荷的QoS必须是原始发布消息的QoS和服务端授予的QoS两者中的最小值。如果原始消息的QoS是1而被授予的最大QoS是0,允许服务端重复发送一个消息的副本给订阅者。
5.2 SUBACK - 订阅确认
服务端发送SUBACK报文给客户端,用于确认它已收到并且正在处理SUBSCRIBE报文。
SUBACK报文包含一个返回码清单,它们指定了SUBSCRIBE请求的每个订阅被授予的最大QoS等级。
5.2.1 固定报头
Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 | |
---|---|---|---|---|---|---|---|---|
byte 1 | MQTT 报文的类型(9 - SUBACK) | Reserved 保留位 | ||||||
9,0x9 - SUBACK | 0 | 0 | 0 | 0 | ||||
byte 2 | 剩余长度 | |||||||
5.2.2 可变报头
可变报头包含等待确认的SUBSCRIBE报文的报文标识符。
byte 1 | 报文标识符 MSB |
---|---|
byte 2 | 报文标识符 LSB |
5.2.3 有效载荷
有效载荷包含一个返回码清单。每个返回码对应等待确认的SUBSCRIBE报文中的一个主题过滤器。返回码的顺序必须和SUBSCRIBE报文中主题过滤器的顺序相同。
下面表格描述了有效载荷中单字节编码的返回码字段。
Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 | |
---|---|---|---|---|---|---|---|---|
byte 1 | 返回码 | |||||||
X | 0 | 0 | 0 | 0 | 0 | X | X |
允许的返回码值:
0x00 - 最大 Qos0
0x01 - 成功 - 最大 Qos1
0x02 - 成功 - 最大 Qos2
0x80 - Failure 失败
0x00, 0x01, 0x02, 0x80之外的SUBACK返回码是保留的,不能使用。
5.3 UNSUBSCRIBE - 取消订阅
客户端发送UNSUBSCRIBE报文给服务端,用于取消订阅主题。
5.3.1 固定报头
Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 | |
---|---|---|---|---|---|---|---|---|
byte 1 | MQTT 报文的类型(10 - UNSUBSCRIBE) | Reserved 保留位 | ||||||
10,0xA - UNSUBSCRIBE | 0 | 0 | 1 | 0 | ||||
byte 2~4 | 剩余长度 | |||||||
UNSUBSCRIBE报文固定报头的第3,2,1,0位是保留位且必须分别设置为0,0,1,0。服务端必须认为任何其它的值都是不合法的并关闭网络连接。
5.3.2 可变报头
可变报头包含一个报文标识符。
byte 1 | 报文标识符 MSB |
---|---|
byte 2 | 报文标识符 LSB |
5.3.3 有效载荷
UNSUBSCRIBE报文的有效载荷包含客户端想要取消订阅的主题过滤器列表。UNSUBSCRIBE报文中的主题过滤器必须是连续打包的UTF-8编码字符串。
UNSUBSCRIBE报文的有效载荷必须至少包含一个消息过滤器。没有有效载荷的UNSUBSCRIBE报文是违反协议的。
byte 1 | Topic长度 MSB |
---|---|
byte 2 | Topic长度 LSB |
byte 3...N | 主题过滤器(Topic Filter) |
byte N+1 | Topic长度 MSB |
byte N+2 | Topic长度 LSB |
byte N+3...X | 主题过滤器(Topic Filter) |
... ... | ... ... |
UNSUBSCRIBE的有效载荷比SUBSCRIBE少了服务质量要求(Requested QoS)。
响应:UNSUBSCRIBE报文提供的主题过滤器(无论是否包含通配符)必须与服务端持有的这个客户端的当前主题过滤器集合逐个字符比较。如果有任何过滤器完全匹配,那么它(服务端)自己的订阅将被删除,否则不会有进一步的处理
如果服务端删除了一个订阅:
- 它必须停止分发任何新消息给这个客户端。
- 它必须完成分发任何已经开始往客户端发送的QoS 1和QoS 2的消息。
- 它可以继续发送任何现存的准备分发给客户端的缓存消息。
服务端必须发送UNSUBACK报文响应客户端的UNSUBSCRIBE请求。UNSUBACK报文必须包含和UNSUBSCRIBE报文相同的报文标识符 。即使没有删除任何主题订阅,服务端也必须发送一个SUBACK响应。
5.4 UNSUBACK - 取消订阅确认
服务端发送UNSUBACK报文给客户端用于确认收到UNSUBSCRIBE报文。
5.4.1 固定报头
Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 | |
---|---|---|---|---|---|---|---|---|
byte 1 | MQTT 报文的类型(11 - UNSUBACK) | Reserved 保留位 | ||||||
11,0xB - UNSUBACK | 0 | 0 | 0 | 0 | ||||
byte 2 | 剩余长度 | |||||||
0x02 |
剩余长度字段:表示可变报头的长度,对UNSUBACK报文这个值等于2。
5.4.2 可变报头
可变报头包含等待确认的UNSUBSCRIBE报文的报文标识符。
byte 1 | 报文标识符 MSB |
---|---|
byte 2 | 报文标识符 LSB |
UNSUBACK报文没有有效载荷。