第三章 – MQTT控制报文 - 3.8 SUBSCRIBE - 订阅主题
3.8 SUBSCRIBE - 订阅主题
客户端向服务端发送SUBSCRIBE报文用于创建一个或多个订阅。每个订阅注册客户端关心的一个或多个主题。为了将应用消息转发给与那些订阅匹配的主题,服务端发送PUBLISH报文给客户端。SUBSCRIBE报文也(为每个订阅)指定了最大的QoS等级,服务端根据这个发送应用消息给客户端。
3.8.1 固定报头
图例 3.20 – SUBSCRIBE报文固定报头
Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
byte 1 | MQTT控制报文类型 (8) | 保留位 | ||||||
1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | |
byte 2 | 剩余长度 |
Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
byte 1 | MQTT控制报文类型 (8) | 保留位 | ||||||
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | |
byte 2 | 剩余长度 |
SUBSCRIBE控制报固定报头的第3,2,1,0位是保留位,必须分别设置为0,0,1,0。服务端必须将其它的任何值都当做是不合法的并关闭网络连接 [MQTT-3.8.1-1]。
剩余长度字段
等于可变报头的长度(2字节)加上有效载荷的长度。
3.8.2可变报头
可变报头包含报文标识符。2.3.1提供了有关报文标识符的更多信息。
可变报头非规范示例
图例 3.21 – 报文标识符等于10的可变报头,非规范示例 展示了报文标识符设置为10时的可变报头。
图例 3.21 – 报文标识符等于10的可变报头,非规范示例
描述 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
---|---|---|---|---|---|---|---|---|---|
报文标识符 | |||||||||
byte 1 | 报文标识符 MSB (0) | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
byte 2 | 报文标识符 LSB (10) | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 |
3.8.3 有效载荷
SUBSCRIBE报文的有效载荷包含了一个主题过滤器列表,它们表示客户端想要订阅的主题。SUBSCRIBE报文有效载荷中的主题过滤器列表必须是1.5.3节定义的UTF-8字符串 [MQTT-3.8.3-1]。服务端应该支持包含通配符(4.7.1节定义的)的主题过滤器。如果服务端选择不支持包含通配符的主题过滤器,必须拒绝任何包含通配符过滤器的订阅请求 [MQTT-3.8.3-2]。每一个过滤器后面跟着一个字节,这个字节被叫做 服务质量要求(Requested QoS)。它给出了服务端向客户端发送应用消息所允许的最大QoS等级。
SUBSCRIBE报文的有效载荷必须包含至少一对主题过滤器 和 QoS等级字段组合。没有有效载荷的SUBSCRIBE报文是违反协议的 [MQTT-3.8.3-3]。有关错误处理的信息请查看4.8节。
请求的最大服务质量等级字段编码为一个字节,它后面跟着UTF-8编码的主题名,那些主题过滤器 /和QoS等级组合是连续地打包。
图例 3.22 – SUBSCRIBE报文有效载荷格式
描述 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
主题过滤器 | ||||||||
byte 1 | 长度 MSB | |||||||
byte 2 | 长度 LSB | |||||||
bytes 3..N | 主题过滤器(Topic Filter) | |||||||
服务质量要求(Requested QoS) | ||||||||
保留位 | 服务质量等级 | |||||||
byte N+1 | 0 | 0 | 0 | 0 | 0 | 0 | X | X |
描述 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
主题过滤器 | ||||||||
byte 1 | 长度 MSB | |||||||
byte 2 | 长度 LSB | |||||||
byte 3..N | 主题过滤器(Topic Filter) | |||||||
服务质量要求(Requested QoS) | ||||||||
保留位 | 服务质量等级 | |||||||
byte N+1 | 0 | 0 | 0 | 0 | 0 | 0 | X | X |
当前版本的协议没有用到服务质量要求(Requested QoS)字节的高六位。如果有效载荷中的任何位是非零值,或者QoS不等于0,1或2,服务端必须认为SUBSCRIBE报文是不合法的并关闭网络连接 [MQTT-3-8.3-4]。
有效载荷非规范示例
图例 3.23 – 有效载荷字节格式非规范示例 展示了 表格 3.5 – 有效载荷非规范示例 中简略描述的SUBSCRIBE报文的有效载荷。
表格 3.5 – 有效载荷非规范示例
主题名 | “a/b” |
---|---|
服务质量要求 | 0x01 |
主题名 | “c/d” |
服务质量要求 | 0x02 |
图例 3.23 – 有效载荷字节格式非规范示例
描述 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
---|---|---|---|---|---|---|---|---|---|
主题过滤器(Topic Filter) | |||||||||
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) | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
主题过滤器(Topic Filter) | |||||||||
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) | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
3.8.4 响应
服务端收到客户端发送的一个SUBSCRIBE报文时,必须使用SUBACK报文响应 [MQTT-3.8.4-1]。SUBACK报文必须和等待确认的SUBSCRIBE报文有相同的报文标识符 [MQTT-3.8.4-2]。
允许服务端在发送SUBACK报文之前就开始发送与订阅匹配的PUBLISH报文。
如果服务端收到一个SUBSCRIBE报文,报文的主题过滤器与一个现存订阅的主题过滤器相同,那么必须使用新的订阅彻底替换现存的订阅。新订阅的主题过滤器和之前订阅的相同,但是它的最大QoS值可以不同。与这个主题过滤器匹配的任何现存的保留消息必须被重发,但是发布流程不能中断 [MQTT-3.8.4-3]。
如果主题过滤器不同于任何现存订阅的过滤器,服务端会创建一个新的订阅并发送所有匹配的保留消息。
如果服务端收到包含多个主题过滤器的SUBSCRIBE报文,它必须如同收到了一系列的多个SUBSCRIBE报文一样处理那个,除了需要将它们的响应合并到一个单独的SUBACK报文发送 [MQTT-3.8.4-4]。
服务端发送给客户端的SUBACK报文对每一对主题过滤器 和QoS等级都必须包含一个返回码。这个返回码必须表示那个订阅被授予的最大QoS等级,或者表示这个订阅失败 [MQTT-3.8.4-5]。服务端可以授予比订阅者要求的低一些的QoS等级。为响应订阅而发出的消息的有效载荷的QoS必须是原始发布消息的QoS和服务端授予的QoS两者中的最小值。如果原始消息的QoS是1而被授予的最大QoS是0,允许服务端重复发送一个消息的副本给订阅者 [MQTT-3.8.4-6]。
非规范示例
对某个特定的主题过滤器,如果正在订阅的客户端被授予的最大QoS等级是1,那么匹配这个过滤器的QoS等级0的应用消息会按QoS等级0分发给这个客户端。这意味着客户端最多收到这个消息的一个副本。从另一方面说,发布给同一主题的QoS等级2的消息会被服务端降级到QoS等级1再分发给客户端,因此客户端可能会收到重复的消息副本。如果正在订阅的客户端被授予的最大QoS等级是0,那么原来按QoS等级2发布给客户端的应用消息在繁忙时可能会丢失,但是服务端不应该发送重复的消息副本。发布给同一主题的 QoS等级1的消息在传输给客户端时可能会丢失或重复。
非规范评注
使用QoS等级2订阅一个主题过滤器等于是说:我想要按照它们发布时的QoS等级接受匹配这个过滤器的消息 。这意味着,确定消息分发时可能的最大QoS等级是发布者的责任,而订阅者可以要求服务端降低QoS到更适合它的等级。
第三章目录 MQTT控制报文
- 3.0 Contents – MQTT控制报文
- 3.1 CONNECT – 连接服务端
- 3.2 CONNACK – 确认连接请求
- 3.3 PUBLISH – 发布消息
- 3.4 PUBACK –发布确认
- 3.5 PUBREC – 发布收到(QoS 2,第一步)
- 3.6 PUBREL – 发布释放(QoS 2,第二步)
- 3.7 PUBCOMP – 发布完成(QoS 2,第三步)
- 3.8 SUBSCRIBE - 订阅主题
- 3.9 SUBACK – 订阅确认
- 3.10 UNSUBSCRIBE –取消订阅
- 3.11 UNSUBACK – 取消订阅确认
- 3.12 PINGREQ – 心跳请求
- 3.13 PINGRESP – 心跳响应
- 3.14 DISCONNECT –断开连接