如何在Python中计算含各组成部分的MQTT数据包大小?
如何正确计算MQTT数据包大小
关于getsizeof计算负载的问题
你的getsizeof(msg.payload)方法不正确。Python的sys.getsizeof()返回的是对象在内存中的总占用大小,包括bytes对象本身的内部结构开销(比如引用计数、类型指针等),而不是负载内容的实际字节长度。
以你给出的负载b'{"0":294.3875741324,"1":292.1924140501}'为例,用len()计算才是它的实际字节数(37字节),而getsizeof()得到的72包含了bytes对象的额外内存开销,完全不能代表负载的真实大小。正确的负载长度计算应该用:
payload_size = len(msg.payload)
MQTT数据包总大小的计算方法
MQTT数据包由4部分组成,总大小是各部分字节数之和:
- 控制头:固定1字节,包含报文类型(如PUBLISH、SUBSCRIBE)和标志位
- 剩余长度:1~4字节,采用可变长度编码,表示「可变头+负载」的总字节数
- 可变长度头:长度取决于报文类型,比如PUBLISH报文的可变头包含主题名(UTF-8编码,前缀2字节表示主题长度+主题内容字节数)、QoS>0时的报文标识符(2字节)
- 负载:实际消息内容,字节数为
len(payload_bytes)
计算步骤示例(以PUBLISH报文为例)
假设你发送的是QoS 0的PUBLISH报文,主题为"device/sensor"(UTF-8编码,长度13字节):
- 控制头:1字节
- 可变头长度:2(主题长度前缀) +13(主题内容)=15字节
- 负载长度:37字节(你的示例负载)
- 剩余长度:15+37=52,可变编码后为1字节(0x34)
- 总大小:1+1+15+37=54字节
剩余长度的可变编码规则
剩余长度的每个字节只用低7位表示数值,最高位是续位标志(1表示后面还有字节,0表示最后一个字节):
- 数值≤127:1字节
- 128~16383:2字节(第一个字节高位置1,低7位存数值的低7位;第二个字节存数值的高7位)
- 以此类推,最多4字节
更简便的计算方式
如果用Python的MQTT库(如paho-mqtt),可以直接构造报文并获取其字节长度,无需手动计算:
import paho.mqtt.packet as packet # 构造PUBLISH报文 pub_pkt = packet.PublishPacket() pub_pkt.topic_name = "device/sensor" pub_pkt.payload = b'{"0":294.3875741324,"1":292.1924140501}' pub_pkt.qos = 0 # 根据实际QoS设置 # 打包成字节流并获取总长度 pkt_bytes = pub_pkt.pack() total_size = len(pkt_bytes) print(total_size) # 输出准确的数据包总大小
内容的提问来源于stack exchange,提问作者user18430327
相关产品推荐
相关产品推荐

