1. MQTT 报文类型概述
MQTT 协议定义了 14种报文类型,每种类型有不同的用途。常见的类型包括:
CONNECT:客户端连接请求
PUBLISH:发布消息(携带应用数据)
SUBSCRIBE:订阅主题
PUBACK:QoS 1消息的确认
PINGREQ/PINGRESP:心跳包
2. 何时接收 PUBLISH 报文?
当以下条件满足时,接收到的报文是 PUBLISH 报文:
客户端已订阅主题:客户端通过 SUBSCRIBE 报文订阅了某个主题。
服务端推送消息:服务端(或另一个客户端)向该主题发布消息,通过 PUBLISH 报文传输。
QoS 匹配:根据 QoS 级别,可能伴随 PUBACK/PUBREC 等确认报文。
3. 如何判断报文类型?
通过 Fixed Header 的第一个字节 判断报文类型:
c
uint8_t packet_type = packet[0] >> 4; // 高4位为报文类型
如果 packet_type == 0x3,则为 PUBLISH 报文。
其他值对应不同报文类型(如 0x2=CONNACK、0x9=SUBACK)。
4. PUBLISH 报文的结构
一个典型的 PUBLISH 报文结构如下:
c
Fixed Header (类型+标志+剩余长度) | Variable Header (主题+Packet ID) | Payload (消息内容)
Fixed Header:必选,包含报文类型(0x3)和 QoS 标志。
Variable Header:包含主题名(UTF-8 字符串)和 Packet ID(QoS > 0 时存在)。
Payload:实际传输的数据(可以是任意二进制内容)。
5. 示例:接收 PUBLISH 报文
假设客户端订阅了主题 /sensor/temperature,当服务端向该主题发布消息时,客户端会收到如下 PUBLISH 报文:
c
Fixed Header:
0x30 // 报文类型=0x3 (PUBLISH), QoS=0, RETAIN=0
0x12 // 剩余长度=18字节
Variable Header:
0x00 0x10 // 主题长度=16字节
"/sensor/temp" // 主题(16字节)
Payload:
"25.5℃" // 消息内容(5字节)
6. 其他常见接收报文

7. 如何验证接收的报文类型?
通过代码解析第一个字节的高4位:
c
void handle_mqtt_packet(uint8_t *packet) {
uint8_t packet_type = packet[0] >> 4;
if (packet_type == 0x3) {
printf("收到 PUBLISH 报文\n");
parse_publish_packet(packet);
} else if (packet_type == 0x2) {
printf("收到 CONNACK 报文\n");
}
// 其他类型处理...
}
总结
属于 PUBLISH 的情况:当客户端订阅主题后接收应用数据时,报文类型为 PUBLISH。
不属于 PUBLISH 的情况:连接确认(CONNACK)、订阅确认(SUBACK)等控制报文。
验证方法:通过报文头的第一个字节高4位判断类型。