MQTT通信协议
MQTT(Message Queuing Telemetry Transport)是一种轻量级的即时通信协议,常用于物联网设备之间的通信。其报文结构由固定报头(Fixed Header)、 可变报头(Variable Header)和有效载荷(Payload)三部分构成。下面为你列举几种常见的 MQTT 报文示例,并对其结构进行解析。
参考文档:
通过网盘分享的文件:MQTT-3.1.1-CN.pdf
链接: https://pan.baidu.com/s/1GU-PXZ4coXZMHElGfQE9BQ 提取码: e2rd
目录
三、有效载荷
4.1 CONNECT 报文(客户端连接请求)
固定报头
可变报头
有效载荷
完整的 CONNECT 报文(十六进制)
4.2 PUBLISH 报文(发布消息)
固定报头
可变报头
有效载荷
完整的 PUBLISH 报文(十六进制,QoS 0)
4.3 SUBSCRIBE 报文(订阅主题)
固定报头
可变报头
有效载荷
完整的 SUBSCRIBE 报文(十六进制)
4.4 PINGREQ 报文(心跳请求)
一、固定报头(2个字节)
1.1控制报文的类型
1.2控制报文类型的标志位
DUP1 =控制报文的重复分发标志
QoS2 = PUBLISH 报文的服务质量等级
RETAIN3 = PUBLISH 报文的保留标志
1.3剩余长度
剩余长度等于可变报头的长度(10 字节)加上有效载荷的长度。
二、可变报头(不同报文,内容不同)
以CONNECT报文为例,包含10个字节,如下:
三、有效载荷
四、举例说明
4.1 CONNECT 报文(客户端连接请求)
用途:客户端借助此报文向服务器发起连接请求。
固定报头
- 报文类型:取值为 1(对应的二进制表示为 0000 0001)。
- 标志位:该字段的后四位(即 D3 - D0)用于表示标志,低 4 位 0000 → CONNECT 报文的标志位必须为 0
- 剩余长度:表示可变报头和有效载荷的总字节数。在这个例子中,假设协议名为 “MQTT”(占 4 字节),协议版本为 4(0x04),连接标志为 0x02(清洁会话 = 1),保持连接时间为 60 秒(0x003C),客户端 ID 为 “client01”(占 7 字节),那么剩余长度的计算方式为:4(协议名) + 1(协议版本) + 2(连接标志 + 保持连接时间) + 1(客户端 ID 长度 MSB) + 1(客户端 ID 长度 LSB) + 7(客户端 ID) = 16,用十六进制表示为 0x10。
固定报头的十六进制表示:10 10(其中,10 是报文类型和标志位,10 是剩余长度)。
可变报头
- 协议名:取值为 “MQTT”,对应的十六进制表示为 00 04 4D 51 54 54(前两个字节 00 04 表示字符串长度为 4)。
- 协议版本:在 MQTT 3.1.1 版本中,该值为 04。
- 连接标志:具体情况如下:
- 用户名标志(U):若设置为 1,则意味着有效载荷中包含用户名。
- 密码标志(P):若设置为 1,则表示有效载荷中包含密码。
- 遗嘱保留(R):在 MQTT 3.1.1 版本中,该位需设置为 0。
- 遗嘱 QoS(Q):当遗嘱标志(D)为 1 时,用于表示遗嘱消息的 QoS 等级。
- 遗嘱标志(D):若设置为 1,则表明存在遗嘱消息。
- 清洁会话(C):若设置为 1,代表开启清洁会话。
- 在此示例中,假设各标志位的设置为:清洁会话 = 1,无遗嘱,无用户名和密码,那么标志位为 0000 0000(即二进制的 0x00)。
- 这里设置为 02(表示清洁会话 = 1)。
- 保持连接时间:以秒为单位,60 秒对应的十六进制表示为 00 3C。
可变报头的十六进制表示:00 04 4D 51 54 54 04 02 00 3C。
有效载荷
- 客户端 ID:设置为 “client01”,其长度为 7 字节,对应的十六进制表示为 00 07 63 6C 69 65 6E 74 30 31(前两个字节 00 07 表示字符串长度为 7)。
- 由于此例中未包含遗嘱、用户名和密码,所以有效载荷仅包含客户端 ID。
有效载荷的十六进制表示:00 07 63 6C 69 65 6E 74 30 31。
完整的 CONNECT 报文(十六进制)
10 10 00 04 4D 51 54 54 04 02 00 3C 00 07 63 6C 69 65 6E 74 30 31
4.2 PUBLISH 报文(发布消息)
用途:客户端或服务器通过该报文发布消息到指定主题。
固定报头
- 报文类型:取值为 3(对应的二进制表示为 0000 0011)。
- 标志位:
- QoS 等级:当 QoS = 1 时,标志位为 00(对于 QoS 0,标志位为 00;QoS 1 为 01;QoS 2 为 10)。
- 保留标志(R):若设置为 1,则表示保留消息。
- 在此示例中,假设 QoS = 0,保留标志 = 0,那么标志位为 00。
- 剩余长度:假设主题名为 “test/topic”(占 10 字节),有效载荷为 “hello mqtt”(占 11 字节),那么剩余长度为 2(主题名长度) + 10(主题名) + 11(有效载荷) = 23,用十六进制表示为 0x17。
固定报头的十六进制表示:30 17。
可变报头
- 主题名:设置为 “test/topic”,其长度为 10 字节,对应的十六进制表示为 00 0A 74 65 73 74 2F 74 6F 70 69 63(前两个字节 00 0A 表示字符串长度为 10)。
- 当 QoS > 0 时,可变报头中会包含报文标识符,但在此例中 QoS = 0,所以不存在该字段。
可变报头的十六进制表示:00 0A 74 65 73 74 2F 74 6F 70 69 63。
有效载荷
- 有效载荷为 “hello mqtt”,对应的十六进制表示为 68 65 6C 6C 6F 20 6D 71 74 74。
完整的 PUBLISH 报文(十六进制,QoS 0)
30 17 00 0A 74 65 73 74 2F 74 6F 70 69 63 68 65 6C 6C 6F 20 6D 71 74 74
4.3 SUBSCRIBE 报文(订阅主题)
用途:客户端通过此报文向服务器订阅一个或多个主题,并指定每个主题的 QoS 等级。
固定报头
- 报文类型:取值为 8(对应的二进制表示为 0000 1000)。
- 标志位:固定为 02(因为 SUBSCRIBE 报文的 QoS 标志位为 0010)。
- 剩余长度:假设报文标识符为 0x0001(占 2 字节),订阅主题为 “test/topic”(占 10 字节),QoS 为 1(占 1 字节),那么剩余长度为 2(报文标识符) + 2(主题名长度) + 10(主题名) + 1(QoS) = 15,用十六进制表示为 0x0F。
固定报头的十六进制表示:82 0F。
可变报头
- 报文标识符:设置为 00 01。
可变报头的十六进制表示:00 01。
有效载荷
- 主题过滤器:设置为 “test/topic”,其长度为 10 字节,对应的十六进制表示为 00 0A 74 65 73 74 2F 74 6F 70 69 63。
- QoS 等级:设置为 01(表示 QoS 1)。
有效载荷的十六进制表示:00 0A 74 65 73 74 2F 74 6F 70 69 63 01。
完整的 SUBSCRIBE 报文(十六进制)
82 0F 00 01 00 0A 74 65 73 74 2F 74 6F 70 69 63 01
4.4 PINGREQ 报文(心跳请求)
功能:客户端发送心跳,维持连接。
报文结构(十六进制示例):
C0 00