一MQTT控制报文简介MQTT控制报文是MQTT协议中数据传输的最小单元是客户端与服务端之间完成所有交互的核心指令载体所有连接建立、消息发布、主题订阅、保活探活等操作都需要通过交换不同类型的控制报文实现。一、通用报文结构所有MQTT控制报文都遵循统一的三段式结构不同报文的差异仅体现在各部分的具体内容上1.‌固定报头‌所有报文强制包含位于报文最起始位置核心字段包括报文类型标识、报文控制标识位、剩余长度可变字节整数编码支持最大256MB的报文长度小尺寸报文仅需1字节即可完成长度标识大幅降低协议开销。其中报文类型字段占用首字节高4位直接决定了当前报文的功能类型。2.‌可变报头‌并非所有报文都包含内容完全由报文类型决定不同报文的字段顺序严格遵循协议规范接收端会按固定顺序完成解析。比如CONNECT报文的可变报头包含协议名、协议版本、连接标识等字段PUBLISH报文的可变报头则包含主题名、报文标识符等字段。3.‌有效载荷‌报文的实际数据承载部分同样仅部分报文包含比如CONNECT报文的有效载荷存放客户端ID、用户名、密码PUBLISH报文的有效载荷存放需要传输的应用消息内容。二、核心报文类型及功能MQTT协议中共有15种控制报文其中日常通信中最常用的常见控制报文可以按功能分为四大类覆盖连接建立、消息传输、订阅管理、连接保活1.连接管理类‌CONNECT客户端完成网络连接后向服务端发送的首个报文用于发起MQTT连接请求携带客户端标识、连接参数、身份认证信息等核心内容。CONNACK服务端收到CONNECT报文后返回的响应报文告知客户端连接结果包含连接状态码、服务端支持的功能属性等信息。DISCONNECT通信任意一方主动发送该报文用于正常终止当前MQTT连接或在出现不可恢复错误时强制断开连接。AUTHMQTT 5.0新增的专属报文仅用于实现增强身份认证流程支持客户端和服务端在连接建立前后完成多轮安全认证交互。2.消息发布类‌PUBLISH用于承载实际应用消息完成发布报文内携带主题名、消息内容同时通过标识位指定当前消息的QoS等级、是否为重传消息、是否为保留消息。PUBACKQoS 1等级消息的确认报文接收方收到QoS 1的PUBLISH报文后返回该报文告知发送方消息已成功接收完成QoS 1的至少送达一次流程。PUBRECQoS 2等级消息的第一步确认报文接收方收到QoS 2的PUBLISH报文后返回该报文标记消息已被接收进入后续的释放流程。PUBRELQoS 2等级消息的第二步交互报文发送方收到PUBREC后发送该报文告知接收方可以完成消息交付。PUBCOMPQoS 2等级消息的最终确认报文接收方收到PUBREL后返回该报文标记整个QoS 2的仅送达一次流程全部完成。3.主题订阅类‌SUBSCRIBE客户端向服务端发起订阅请求的报文携带需要订阅的主题过滤器列表指定对应主题的消息推送规则。SUBACK服务端收到SUBSCRIBE报文后返回的响应报文告知客户端每个订阅主题的处理结果。UNSUBSCRIBE客户端向服务端发起取消订阅的报文指定需要移除的主题过滤器。UNSUBACK服务端收到UNSUBSCRIBE报文后返回的响应报文确认取消订阅操作已完成。4.连接保活类‌PINGREQ客户端定期向服务端发送的探活请求报文仅包含固定报头用于告知服务端自身仍处于活跃状态维持长连接有效性。PINGRESP服务端收到PINGREQ后返回的响应报文告知客户端服务端运行正常以此完成双向的连接状态校验。二 解析MQTT控制报文官方文档:官方文档这里我们选取日常调试中最常见的几类MQTT报文结合真实抓包得到的十六进制原始数据一步步完成逐字节解析覆盖连接建立、订阅、消息发布、断开全流程场景MQTT固定报头报文类型、标志位、剩余长度MQTT固定报头的解析可以按照标准化的分步流程完成适配所有MQTT控制报文同时支持嵌入式设备、通用服务端等不同运行环境具体解析方法如下MQTT Control Packets第一步提取首字节拆分4个核心标志位固定报头的第1个字节是8位二进制结构直接按位拆分即可得到4个关键信息{报文类型标志位‌DUP重发标志‌、‌QoS等级‌、RETAIN保留标志‌}‌报文类型‌取该字节的高4位bit7~bit4对照MQTT协议的报文类型表就能识别当前是CONNECT、PUBLISH、PINGREQ等14种标准控制报文0和15为协议保留的非法类型收到后需主动断开连接。标志位FlagsDUP重发标志‌‌QoS等级‌‌RETAIN保留标志‌The remaining bits [3-0] of byte 1 in the Fixed Header contain flags specific to each MQTT Control Packet type as shown below. Where a flag bit is marked as “Reserved”, it is reserved for future use and MUST be set to the value listed [MQTT-2.1.3-1]. If invalid flags are received it is a Malformed Packet. Refer to section 4.13 for details about handling errors.‌DUP重发标志‌取第3位bit3值为1代表该报文是网络重传的副本仅在PUBLISH报文中生效‌QoS等级‌取第2、1位bit2~bit1仅对PUBLISH报文有效对应0最多一次、1至少一次、2仅一次三个传输可靠性等级其余报文该位为协议规定的固定值。‌RETAIN保留标志‌取第0位bit0仅对PUBLISH报文生效值为1代表该消息是服务端存储的主题离线保留消息。第二步解析变长编码的剩余长度字段剩余长度可变报头有效载荷剩余长度是固定报头中从第2字节开始的可变字段采用“7位数据最高位续传标记”的压缩编码方式最多占用4字节解析规则如下逐字节读取后续数据每个字节的低7位作为有效数据位最高位bit7作为续传标记如果最高位为1说明后面还有字节属于剩余长度字段如果最高位为0说明这是剩余长度的最后一个字节。按权重累加计算最终数值公式为其中a是第一个字节的低7位值b是第二个字节的低7位值以此类推最多支持4个字节的计算。举个实际例子如果读取到剩余长度的两个字节是0x97、0x01拆分后a23、b1计算得到剩余长度23 1×128 151代表后续可变报头有效载荷的总字节数为151。第三步完成解析后的校验与后续处理合法性校验剩余长度的总字节数不能超过4且最终计算出的数值不能超过协议规定的268435455字节约256MB如果解析出非法值直接丢弃该报文。定位后续报文位置结合固定报头自身的总长度首字节1字节 剩余长度的字节数就能直接定位到可变报头的起始偏移位置基于解析出的报文类型和剩余长度继续完成后续可变报头和有效载荷的解析工作。嵌入式开发场景的参考解析实现在资源受限的嵌入式设备中可以直接用位域结构体定义固定报头结构快速完成首字节的拆分解析typedefstruct{uint8_tmessage_type:4;// 报文类型占4位uint8_tdup_flag:1;// 重发标志占1位uint8_tqos_level:2;// QoS等级占2位uint8_tretain:1;// 保留标志占1位}mqtt_fixed_header_first_byte_t;再配合循环逐字节读取剩余长度字段就能在低算力的物联网设备上高效完成固定报头解析。示例1CONNECT 连接请求报文原始十六进制报文10 29 00 04 4D 51 54 54 04 C2 00 3C 00 0A 30 33 30 34 30 35 30 36 00 06 70 75 62 6C 69 63 00 09 70 61 70 70 75 62 6C 69 63固定报头解析‌首字节0x10高4位为0001对应报文类型为CONNECT低4位全0符合CONNECT报文的标志位要求。第二个字节0x29十进制为41代表后续可变报头有效载荷的总长度为41字节。可变报头解析‌00 04标识后续协议名字段的长度为4字节对应内容4D 51 54 54ASCII解码后为MQTT。0x04协议级别字段对应MQTT 3.1.1版本。0xC2连接标志位二进制为11000010代表启用用户名、密码开启清理会话无遗嘱消息。00 3C保持连接时长十进制为60秒。有效载荷解析‌00 0A标识后续客户端ID长度为10字节对应内容30 33 30 34 30 35 30 36解码后为03040506。00 06标识后续用户名长度为6字节对应内容70 75 62 6C 69 63解码后为public。00 09标识后续密码长度为9字节对应内容70 61 70 70 75 62 6C 69 63解码后为pappublic。示例2CONNACK 连接确认报文原始十六进制报文20 02 00 00固定报头解析‌首字节0x20高4位为0010对应报文类型为CONNACK低4位全0。第二个字节0x02代表后续可变报头总长度为2字节。可变报头解析‌0x00当前会话标志位为0代表服务端没有恢复之前的历史会话本次为全新会话。0x00连接返回码为0代表连接成功建立。示例3SUBSCRIBE 订阅请求报文原始十六进制报文82 1C 00 01 00 17 6A 6B 2F 63 6F 6D 6D 61 6E 64 2F 72 65 61 6C 79 63 6F 6E 74 72 6F 6C 00固定报头解析‌首字节0x82高4位为1000对应报文类型为SUBSCRIBE低4位的保留位为2符合协议要求。第二个字节0x1C十进制为28代表后续可变报头有效载荷总长度为28字节。可变报头解析‌00 01报文标识符十进制为1用于匹配后续的订阅响应报文。有效载荷解析‌00 17标识后续主题过滤器长度为23字节对应内容6A 6B 2F 63 6F 6D 6D 61 6E 64 2F 72 65 61 6C 79 63 6F 6E 74 72 6F 6C解码后为主题jk/command/realycontrol。末尾0x00指定该订阅的消息QoS等级为0。示例4PUBLISH 消息发布报文QoS 0原始十六进制报文30 22 00 16 6A 6B 2F 72 65 74 75 72 6E 2F 72 65 61 6C 79 63 6F 6E 74 72 6F 6C 31 32 39 38 37固定报头解析‌首字节0x30高4位为0011对应报文类型为PUBLISH低4位全0代表非重传消息、QoS等级为0、非保留消息。第二个字节0x22十进制为34代表后续可变报头有效载荷总长度为34字节。可变报头解析‌00 16标识后续主题名长度为22字节对应内容6A 6B 2F 72 65 74 75 72 6E 2F 72 65 61 6C 79 63 6F 6E 74 72 6F 6C解码后为主题jk/return/realycontrol。有效载荷解析‌剩余字节31 32 39 38 37解码后为消息内容12987。示例5DISCONNECT 断开连接报文MQTT 5.0原始十六进制报文E0 02 8E 00固定报头解析‌首字节0xE0高4位为1110对应报文类型为DISCONNECT低4位全0。第二个字节0x02代表后续可变报头总长度为2字节。可变报头解析‌0x8E原因码对应“Session taken over”代表当前连接被使用相同Client ID的新连接抢占服务端主动断开当前连接。0x00属性长度为0该报文没有额外扩展属性。三MQTT控制报文的使用场景MQTT不同类型的控制报文会根据物联网场景的通信可靠性、带宽资源、业务优先级需求在不同环节发挥专属作用以下是结合真实业务场景的典型使用示例一、智能家居场景家庭设备联动通信这是MQTT最常见的民用场景设备普遍带宽有限、对控制可靠性有基础要求各类控制报文会形成完整的联动闭环1.智能门锁上电后首先发送‌CONNECT‌报文携带设备ID、家庭WiFi下的身份凭证连接家庭本地MQTT网关网关返回‌CONNACK‌确认连接成功门锁正式接入家庭设备网络。2.门锁主动发送‌SUBSCRIBE‌报文订阅home/alarm/set主题网关返回‌SUBACK‌确认订阅生效后续安防系统的报警指令就能直接推送到门锁。3.当用户通过手机APP触发离家布防指令APP作为发布者发送QoS 1等级的‌PUBLISH‌报文到home/alarm/set主题网关转发给门锁后门锁返回‌PUBACK‌确认已收到布防指令避免出现指令丢失导致安防失效的问题。4.门锁每30秒发送一次‌PINGREQ‌心跳报文网关返回‌PINGRESP‌响应维持长连接不被家庭路由器的NAT机制断开保证随时能接收远程控制指令。5.当用户在家中手动解除布防门锁发送‌UNSUBSCRIBE‌报文取消订阅报警主题网关返回‌UNSUBACK‌确认后续不再向门锁推送相关报警指令。6.设备正常断电时发送‌DISCONNECT‌报文主动断开连接网关及时更新设备在线状态避免误判设备离线触发误报警。二、工业物联网场景高危设备安全控制工业场景对数据可靠性要求极高涉及设备安全的操作必须保证消息不丢、不重复执行会用到全流程的QoS 2等级控制报文交互1.工厂车间的高温反应釜控制器通过有线工业网络发送‌CONNECT‌报文接入厂区工业MQTT服务器携带设备专属的加密认证信息服务器校验通过后返回‌CONNACK‌完成接入。2.控制器订阅factory/reactor/emergency_stop紧急停止主题服务器返回‌SUBACK‌确认订阅。3.当车间烟雾传感器触发火灾预警监控系统发布QoS 2等级的紧急停止指令首先发送‌PUBLISH‌报文给反应釜控制器控制器收到后返回‌PUBREC‌报文确认已接收指令监控系统收到后再发送‌PUBREL‌报文通知控制器执行停机关闭操作控制器执行完成后返回‌PUBCOMP‌报文整个四步交互完全保证紧急停止指令仅被执行一次不会因为网络重传导致重复操作引发二次安全事故。4.车间传感器的常规温度数据采集使用QoS 0等级的‌PUBLISH‌报文直接上传不需要额外确认在大量传感器并发上报时能极大节省工业带宽资源避免网络拥塞。三、智慧城市场景低功耗表计数据上报水表、电表这类电池供电的智慧城市终端长期处于低功耗休眠状态网络信号差、带宽极窄控制报文的轻量化特性完全适配这类场景1.智能电表每小时唤醒一次发送超短的‌CONNECT‌报文接入城市物联网MQTT平台平台返回‌CONNACK‌完成快速连接整个连接过程仅消耗极少量电量。2.电表使用QoS 1等级的‌PUBLISH‌报文上传当前用电量数据平台收到后返回‌PUBACK‌确认电表收到确认后立刻进入休眠状态既保证用电量数据不会丢失又最大程度降低功耗延长电池使用寿命。3.这类低功耗设备不需要维持长连接不需要定期发送心跳报文每次仅在数据上报时完成短连接交互上报完成后直接发送‌DISCONNECT‌断开连接完全适配窄带物联网的低功耗运行规则。四、移动推送场景移动端消息通知手机APP的即时消息推送场景网络环境不稳定、频繁切换WiFi/移动网络控制报文的保活机制能保证消息不遗漏1.手机端的推送服务发送‌CONNECT‌报文接入MQTT推送服务器携带用户专属的设备标识服务器返回‌CONNACK‌完成连接。2.推送服务订阅用户专属的通知主题服务器返回‌SUBACK‌确认订阅。3.推送服务设置60秒的保活间隔定期发送‌PINGREQ‌报文服务器返回‌PINGRESP‌响应在移动网络频繁切换的弱网环境下维持长连接的有效性避免被运营商网络主动断开保证即时聊天消息、系统通知能实时推送到手机端。