PUBLISH报文及其响应
PUBLISH控制报文是指从Client端向Broker端或者Broker端向Client端传输一个应用消息,用于消息的发布。
PUBLISH报文头的第一个字节中,bit2和bit1用于设置QoS级别,可设置为0,1,2。MQTT协议规定,PUBLISH报文根据不同的QoS级别,其报文响应机制不同,如下图所示。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ezyAj0L9-1590393201757)(C:\Users\ThinkPad\AppData\Roaming\Typora\typora-user-images\image-20200521101412930.png)]
固定报头
如下表格描述了PUBLISH报文固定报头格式。
字段 | 描述 |
byte1 | bit7-bit4:MQTT控制报文类型 bit3: DUP bit2-bit1:QoS级别 bit0:RETAIN |
byte2… | 剩余长度 |
重发标志DUP
如果DUP被设置为0,表示这是Clinet端或者Broker端第一次请求发送这个报文。如果DUP被设置为1,表示这可能是一个报文请求的重发。
Client端或Broker端请求重发一个PUBLISH报文时,必须将DUP标志设置为1.对于QoS为0的报文,DUP标志必须设置为0.
Broker端发送PUBLISH报文给订阅者时,收到的PUBLISH报文的DUP标志的值不会被传播。Client发送的PUBLISH和收到的PUBLISH中的DUP标志是独立设置的,没有互相关系,其值必须单独的根据发送的PUBLISH报文是否是一个重发来确定。
QoS服务质量等级
QoS字段表示应用消息分发的服务质量等级。如下表格所示
QoS | bit2 | bit1 | 描述 |
0 | 0 | 0 | 最多分发一次 |
1 | 0 | 1 | 至少分发一次 |
2 | 1 | 0 | 只分发一次 |
- | 1 | 1 | 保留 |
PUBLISH报文不能将QoS所有的位都设为1。如果收到的QoS所有位都为1,必须关闭网络连接。
RETAIN保留保留标志位
如果Client端发送给Broker端的PUBLISH报文的RETAIN位被设置为1,Broker端必须存储这个应用消息和它的QoS,以便可以分发给未来的主题名匹配的订阅者。一个新的订阅创建时,对每个匹配的主题名,如果存在最近保留的消息,它必须被发送给订阅者。如果Broker端收到一条保留标志为1的QoS0消息,它必须丢弃之前为那个主题保留的任何消息,并且应该将这个新的QoS0消息当做那个主题的新的保留消息,但是任何时候都可以选择丢弃它,如果这种情况发生了,那么该主题将没有保留消息。
Broker端发送PUBLISH报文给Clinet端时,如果消息是作为Client端一个新订阅的结果发送,必须将报文的保留标志位设为1。当一个PUBLISH报文发送给Client端是因为匹配一个已建立的订阅时,Broker端必须将保留标志位设为0,不管它收到的这个消息中保留标志的值是多少。
保留标志位为1,有效载荷为零字节的PUBLISH报文会被Broker端当作正常消息处理,它会被发送给订阅主题匹配的Client端。此外,同一个主题下任何现存的保留信息必须被移除,因此这个主题之后的任何订阅者都不会受到一个保留信息。
保留标志为1且有效载荷为零字节的PUBLISH报文会被Broker端“当作正常”消息处理,它会被发送给订阅主题匹配的Client端。此外,同一个主题下任何现存的保留消息必须被移除,因此这个主题之后的任何订阅者都不会收到一个保留消息 。“当作正常”意思是现存的Client端收到的消息中保留标志未被设置。Broker端不能存储零字节的保留消息 。如果Client端发给Broker端的PUBLISH报文的保留标志位0,Broker端不能存储这个消息也不能移除或替换任何现存的保留消息 。
如果Client端发给Broker端的PUBLISH报文的保留标志位0,Broker端不能存储这个消息也不能移除或替换任何现存的保留消息。
剩余长度
等于可变报头的长度加上有效载荷的长度。
可变报头
可变报头组成如下表所示:
字段 | 描述 |
Topic Name主题名 | 例如:a,b, temperature |
Packet Identifier报文标识符 | 10 |
主题名
主题名(Topic Name)用于识别有效载荷数据应该被发布到哪一个信息通道。
主题名必须是PUBLISH报文可变报头的第一个字段,必须是 UTF-8编码的字符串,且不能 包含通配符。
Broker端发送给订阅Client端的PUBLISH报文的主题名必须匹配该订阅的主题过滤器。
报文标识符
只有当QoS等级是1或2时,报文标识符(Packet Identifier)字段才能出现在PUBLISH报文中,可以参考《MQTT报文分析》。
有效载荷
有效载荷包含将被发布的应用消息。数据的内容和格式是应用特定的。有效载荷的长度这样计算:用固定报头中的剩余长度字段的值减去可变报头的长度。包含零长度有效载荷的PUBLISH报文是合法的。
动作 Actions
Client端使用PUBLISH报文发送应用消息给Broker端,目的是分发到其它订阅匹配的Client端。
Broker端使用PUBLISH报文发送应用消息给每一个订阅匹配的Client端。
Client端使用带通配符的主题过滤器请求订阅时,Client端的订阅可能会重复,因此发布的消息可能会匹配多个过滤器。对于这种情况,Broker端必须将消息分发给所有订阅匹配的QoS等级最高的Client端 。Broker端之后可以按照订阅的QoS等级,分发消息的副本给每一个匹配的订阅者。
收到一个PUBLISH报文时,接收者的动作取决于QoS等级。如果Broker端实现不授权某个Client端发布PUBLISH报文,它没有办法通知那个Client端。它必须按照正常的QoS规则发送一个正面的确认,或者关闭网络连接。
PUBACK-发布确认
PUBACK报文是对QoS 1等级的PUBLISH报文的响应,其组成如下图所示
字段 | 描述 |
固定报头 | 2字节 |
可变报头 | 2字节 |
固定报头
固定报头如下表所示
字段 | 描述 |
byte1 | bit7-bit4:MQTT报文类型 bit3-bit0:保留位 |
byte2 | 剩余长度:PUBACK报文头这个值为0x02 |
可变报头
可变报头如下表所示
字段 | 描述 |
byte1 | 报文标识符MSB |
byte2 | 报文标识符LSB |
动作
参考后续文章,MQTT协议的操作行为
PUBREC – 发布收到(QoS 2,第一步)
PUBREC报文是对QoS等级2的PUBLISH报文的响应,它是QoS 2等级协议交换的第二个报文,其组成如下表所示:
字段 | 描述 |
固定报头 | 2字节 |
可变报头 | 2字节 |
固定报头
固定报头如下表所示
字段 | 描述 |
byte1 | bit7-bit4:MQTT报文类型 bit3-bit0:保留位 |
byte2 | 剩余长度:PUBREC报文头这个值为0x02 |
可变报头
可变报头如下表所示
字段 | 描述 |
byte1 | 报文标识符MSB |
byte2 | 报文标识符LSB |
动作
参考后续文章,MQTT协议的操作行为
PUBREL – 发布释放(QoS 2,第二步)
PUBREL报文是对PUBREC报文的响应。它是QoS 2等级协议交换的第三个报文,其组成如下所示:
字段 | 描述 |
固定报头 | 2字节 |
可变报头 | 2字节 |
固定报头
固定报头如下表所示:
字段 | 描述 |
byte1 | bit7-bit4:MQTT报文类型 bit3-bit0:保留位,必须设置为0010 |
byte2 | 剩余长度:PUBREL报文头这个值为0x02 |
可变报头
可变报头如下表所示
字段 | 描述 |
byte1 | 报文标识符MSB |
byte2 | 报文标识符LSB |
动作
参考后续文章,MQTT协议的操作行为
PUBCOMP – 发布完成(QoS 2,第三步)
PUBCOMP报文是对PUBREL报文的响应。它是QoS 2等级协议交换的第四个也是最后一个报文,其组成如下表所示:
字段 | 描述 |
固定报头 | 2字节 |
可变报头 | 2字节 |
固定报头
固定报头如下表所示
字段 | 描述 |
byte1 | bit7-bit4:MQTT报文类型 bit3-bit0:保留位 |
byte2 | 剩余长度:PUBCOMP报文头这个值为0x02 |
可变报头
可变报头如下表所示
字段 | 描述 |
byte1 | 报文标识符MSB |
byte2 | 报文标识符LSB |
动作
参考后续文章,MQTT协议的操作行为
引用
1 《MQTT协议中文版本》:https://mcxiaoke.gitbooks.io/mqtt-cn/content/
可变报头如下表所示
字段 | 描述 |
byte1 | 报文标识符MSB |
byte2 | 报文标识符LSB |
动作
参考后续文章,MQTT协议的操作行为
引用
1 《MQTT协议中文版本》:https://mcxiaoke.gitbooks.io/mqtt-cn/content/
2 《MQTT Version 3.1.1》