在上期中,我们介绍了MQTT 5.0的CONNECT和CONNACK数据包:
MQTT Packet详解【01】:CONNECT & CONNACK
现在,我们将介绍用于在MQTT中传递应用程序消息的PUBLISH包及其响应包。
无论是客户端向服务器发布消息,还是服务器向订阅者转发消息,都需要PUBLISH数据包。确定消息方向的主题、消息的实际内容和QoS级别都包含在PUBLISH数据包中。
在客户端和服务器端之间的消息传递过程中,除了PUBLISH包外,还有四个包:PUBACK、PUBREC、PUBREL和PUBCOMP。它们用于实现MQTT的QoS 1和QoS 2消息机制。
我们使用MQTTX CLI将三个具有不同QoS级别的消息发布到公共MQTT服务器,并使用Wireshark捕获在客户端和服务器之间来回传输的MQTT数据包。在Linux中,您可以使用tcpdump捕获数据包,然后将其导入Wireshark进行查看。
以下是本示例中使用的MQTTX CLI命令。为了显示PUBLISH数据包的属性,这些命令还设置了Message Expiry Interval和Response Topic属性:
mqttx pub --hostname broker.emqx.io --mqtt-version 5 \ --topic request --qos 0 --message "This is a QoS 0 message" \ --message-expiry-interval 300 --response-topic response
以下是Wireshark捕获的QoS为0的PUBLISH数据包:
此十六进制字节串对应于以下数据包内容:
当我们只修改MQTTX CLI命令中的QoS选项并将其设置为1时,我们将看到服务器在收到PUBLISH后回复PUBACK数据包。它们的数据包如下。
此时,PUBLISH数据包中的第一个字节已从0x30
更改为0x32
,表明这是一条QoS 1消息。
PUBACK数据包结构相对简单,如您所见,Reason Code为0x10,表示消息已收到,但没有匹配的订阅者。一旦有人订阅了主题请求
,PUBACK数据包中的Reason Code就会变为0x00
,表示消息已经收到,并且有匹配的订阅者。
继续使用MQTTX CLI发布QoS 2消息,我们将看到客户机和服务器之间有两轮消息交换。Wireshark会告诉我们这些数据包分别是PUBLISH、PUBREC、PUBREL和PUBCOMP,它们都有相同的数据包标识符0x11c2
:
我们如何从由十六进制字节组成的数据包数据中准确地确定它是否是PUBLISH数据包,它的QoS级别是什么,以及它的响应数据包中的Reason Code是什么?下面对这些数据包的介绍将回答这些问题。
PUBLISH包结构
Fixed Header固定头
在PUBLISH包的Fixed Header中,第一字节的高4位固定为3(0 b 0011),低4位由以下三个字段组成:
在此之后是剩余长度字段,其指示当前分组的剩余部分中的字节数。
PUBLISH数据包的变量报头按顺序包含以下字段:
我们发送的应用程序消息的内容存储在PUBLISH数据包的Payload中。它可以携带任何格式的应用程序消息,如JSON、ProtoBuf等。
Fixed Header固定头
固定报头中第一个字节的高4位固定为4(0b0100),指示这是PUBACK分组。较低的4位被保留并且全部被设置为0。
紧随其后的是剩余长度字段,它指示当前数据包中剩余的字节数。
Variable Header 变量头
PUBACK包的可变头部按顺序包含以下字段:
PUBREC、PUBREL、PUBCOMP数据包结构
PUBREC、PUBREL、PUBCOMP的包结构与PUBACK基本一致。它们的主要区别在于固定报头中的数据包类型字段的值以及可以使用的原因代码。
数据包类型字段的值为5,表示这是一个PUBREC数据包;如果值为6,表示这是一个PUBREL数据包;如果值为7,表示这是一个PUBCOMP数据包。
PUBREC作为QoS 2消息流中PUBLISH报文的确认报文,可以使用与PUBACK完全相同的原因码。如下图所示:
PUBREL和PUBCOMP数据包可用的原因代码如下:
结论
PUBLISH包中的Topic决定了消息的方向,QoS决定了消息的可靠性。它还确定在传输期间将使用哪些数据包。PUBACK数据包用于QoS 1消息,PUBREC、PUBREC和PUBCOMP数据包用于QoS 2消息。当QoS大于0时,数据包还需要包含数据包标识符,以将PUBLISH数据包与其响应数据包相关联。
PUBLISH数据包的Payload不限制数据类型,因此我们可以传输任何格式的应用程序消息。此外,属性Properties可以满足我们更多场景的需求。例如,Topic Expiry可以减少每条消息的大小,Message Expiry Interval可以为时间敏感的消息设置过期时间等等。
PUBLISH包的这些响应包不仅向发送方表示消息已经收到,还通过Reason Code进一步表示发布结果。所以当订阅者无法接收消息时,我们也可以通过发布者收到的响应包中的原因代码来排查问题。
参考链接:
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有