目录
2.1 MQTT 控制报文的结构
2.2 固定报头
2.2.1 控制报文的类型
2.2.2 控制报文类型的标志位
2.2.3 剩余长度
2.3 可变报头
2.4 有效载荷
2.1 MQTT 控制报文的结构
MQTT控制报文由三部分组成:
MQTT 控制报文的结构
名称 EN |
名称 CN |
所属情况 |
Fixed Header |
固定报头 |
所有控制报文都包含 |
Variable Header |
可变报头 |
部分控制报文包含 |
Payload |
有效载荷 |
部分控制报文包含 |
2.2 固定报头
每个 MQTT 控制报文都包含一个固定报头。固定报头的数据长度为 2~5字节。(Byte = 8bit)
固定报头的格式:(MSB,高位在前)
固定报头的数据格式
Byte - Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
Byte 1 |
MQTT 控制报文的类型(1 ~ 14) |
指定控制报文类型的标志位 |
Byte 2~5 |
剩余长度(1~4 Byte) |
-
剩余长度字段的长度,取决于帧长度,详细计算方法见 2.2.3章节。
2.2.1 控制报文的类型
位置:固定报头中,第 1 个字节的 Bit 7~4。
控制报文的定义如下:(0/15是保留位,无用。有效类型为 1~14)
MQTT 控制报文的类型
报文类型 |
功能描述 |
流动方向 |
值 |
固定报头 |
可变报头 |
报文标识符 |
载荷 |
CONNECT |
客户端请求连接服务端 |
C -> S |
1 |
有 |
有 |
无 |
有 |
CONNACK |
服务端确认连接建立 |
S -> C |
2 |
有 |
有 |
无 |
有 |
PUBLISH |
发布消息 |
C <=> S |
3 |
有 |
有 |
有(Qos>0) |
有 |
PUBACK |
收到发布消息确认(QoS1等级) |
C <=> S |
4 |
有 |
有 |
有 |
无 |
PUBREC |
发布消息收到(QoS2等级) |
C <=> S |
5 |
有 |
有 |
有 |
无 |
PUBREL |
发布消息释放(QoS2等级) |
C <=> S |
6 |
有 |
有 |
有 |
无 |
PUBCOMP |
发布消息完成(QoS2等级) |
C <=> S |
7 |
有 |
有 |
有 |
无 |
SUBSCRIBE |
订阅请求 |
C -> S |
8 |
有 |
有 |
有 |
有 |
SUBACK |
订阅确认 |
S -> C |
9 |
有 |
有 |
有 |
有 |
UNSUBSCRIBE |
取消订阅 |
C -> S |
10 |
有 |
有 |
有 |
有 |
UNSUBACK |
取消订阅确认 |
S -> C |
11 |
有 |
有 |
有 |
无 |
PINGREQ |
(保活)心跳请求 |
C -> S |
12 |
有 |
无 |
无 |
无 |
PINGRESP |
心跳响应 |
S -> C |
13 |
有 |
无 |
无 |
无 |
DISCONNECT |
客户端断开连接 |
C -> S |
14 |
有 |
无 |
无 |
无 |
-
Qos:Quality of service,服务质量。Qos 0/1/2 为MQTT规定的服务质量等级,其代表消息传递时不同的可靠程度。
- 其中,5、6、7为 Qos2时才会有的控制报文。
2.2.2 控制报文类型的标志位
位置:固定报头中,第 1 个字节的 Bit 3~0。
报文类型-标志位
控制报文 |
固定报头标志 |
Bit 3 |
Bit 2 |
Bit 1 |
Bit 0 |
CONNECT |
Reserved |
0 |
0 |
0 |
0 |
CONNACK |
Reserved |
0 |
0 |
0 |
0 |
PUBLISH |
Used in MQTT 3.1.1 |
DUP1 |
QoS2 |
QoS2 |
RETAIN3 |
PUBACK |
Reserved |
0 |
0 |
0 |
0 |
PUBREC |
Reserved |
0 |
0 |
0 |
0 |
PUBREL |
Reserved |
0 |
0 |
0 |
0 |
PUBCOMP |
Reserved |
0 |
0 |
0 |
0 |
SUBSCRIBE |
Reserved |
0 |
0 |
0 |
0 |
SUBACK |
Reserved |
0 |
0 |
0 |
0 |
UNSUBSCRIBE |
Reserved |
0 |
0 |
0 |
0 |
UNSUBACK |
Reserved |
0 |
0 |
0 |
0 |
PINGREQ |
Reserved |
0 |
0 |
0 |
0 |
PINGRESP |
Reserved |
0 |
0 |
0 |
0 |
DISCONNECT |
Reserved |
0 |
0 |
0 |
0 |
- DUP1 =控制报文的重复分发标志
- QoS2 = PUBLISH报文的服务质量等级
- RETAIN3 = PUBLISH报文的保留标志
- PUBLISH控制报文中的DUP, QoS和RETAIN标志的描述见 3.3.1节。
2.2.3 剩余长度
- 位置:固定报头中,从第2个字节开始。
- 剩余长度等于可变报头的长度(10字节)加上有效载荷的长度。
- 剩余长度(Remaining Length)表示当前报文剩余部分的字节数,包括可变报头和负载的数据。
- 剩余长度不包括用于编码剩余长度字段本身的字节数。
剩余长度字段 的帧格式:
帧格式 - 剩余长度字段
第1个字节 |
第2个字节 |
... |
Bit 7 |
Bit 6:0 |
Bit 7 |
Bit 6:0 |
... |
进位标志位 |
长度低字节 |
进位标志位 |
长度高字节 |
... |
-
剩余长度字段 的字节长度:最少1个字节,最多4个字节。
-
剩余长度字段 可以表示的长度:1个字节时,可以表示剩余 0~127 长度。4个字节时,最大表示长度为 2^(7*4) - 1 = 2^28 - 1 = 268435455 长度
剩余长度字段 表示的字节长度
字节数 |
表示长度的最小值(字节) |
表示长度的最大值(字节) |
1 |
0 |
2^7 - 1 = 127 |
2 |
2^7 = 128 |
2^(7*2) - 1 = 16383 |
3 |
2^(7*2) = 16384 |
2^(7*3) - 1 = 2097151 |
4 |
2^(7*3) = 2097152 |
2^(7*4) - 1 = 268435455 |
之所以1个字节不能表示 2^8 - 1 = 255长度,是因为:每个字节的最高位 Bit7,并不表示数据,是进位标志位。
假设本帧剩余字节为 200,计算剩余长度字段。
- 使用电脑计算器,将 200 转换为二进制 1100 1000(MSB高位在前)
- 从右侧低位每7Bit进行一次拆分,依次拆分出:
- 第1个字节为 100 1000,有进位,高位加上进位1为 1100 1000 = 0xC8 (16进制)。
- 第2个字节为 1,无进位,为 1 = 0x01 (16进制)。
那么对应的 字节长度的帧格式如下表:
|
第1个字节 |
第2个字节 |
|
Bit 7 |
Bit 6:0 |
Bit 7 |
Bit 6:0 |
|
进位标志位 |
|
进位标志位 |
|
2进制 |
1 |
100 1000 |
0 |
000 0001 |
2进制 |
1100 1000 |
0000 0001 |
16进制 |
0xC8 |
0x01 |
假设本帧剩余字节为 1000,计算剩余长度字段。
- 使用电脑计算器,将 1000 转换为二进制 11 1110 1000(MSB高位在前)
- 从右侧低位每7Bit进行一次拆分,依次拆分出:
- 第1个字节为 110 1000,有进位,高位加上进位1为 1110 1000 = 0xE8 (16进制)。
- 第2个字节为 11 1,无进位,为 11 1 = 0x07 (16进制)。
那么对应的 字节长度的帧格式如下表:
|
第1个字节 |
第2个字节 |
|
Bit 7 |
Bit 6:0 |
Bit 7 |
Bit 6:0 |
|
进位标志位 |
|
进位标志位 |
|
2进制 |
1 |
110 1000 |
0 |
000 0111 |
2进制 |
1110 1000 |
0000 0111 |
16进制 |
0xE8 |
0x07 |
假设本帧剩余字节为 100,000,000,计算剩余长度字段。
- 使用电脑计算器,将 100,000,000 转换为二进制 101 1111 0101 1110 0001 0000 0000(MSB高位在前)
- 从右侧低位每7Bit进行一次拆分,依次拆分出:
- 第1个字节为 000 0000,有进位,高位加上进位1为 1000 0000 = 0x80 (16进制)。
- 第2个字节为 10 0001 0,有进位,高位加上进位1为 1100 0010 = 0xC2 (16进制)。
- 第3个字节为 1 0101 11,有进位,高位加上进位1为 1101 0111 = 0xD7 (16进制)。
- 第4个字节为 101 111 = 00,无进位,为 10 1111 = 0x2F (16进制)。
那么对应的 字节长度的帧格式如下表:
|
第1个字节 |
第2个字节 |
第3个字节 |
第4个字节 |
|
Bit 7 |
Bit 6:0 |
Bit 7 |
Bit 6:0 |
Bit 7 |
Bit 6:0 |
Bit 7 |
Bit 6:0 |
|
进位标志位 |
|
进位标志位 |
|
进位标志位 |
|
进位标志位 |
|
2进制 |
1 |
000 0000 |
1 |
100 0010 |
1 |
101 0111 |
0 |
010 1111 |
2进制 |
1000 0000 |
1100 0010 |
1101 0111 |
0010 1111 |
16进制 |
0x80 |
0xC2 |
0xD7 |
0x2F |
2.3 可变报头
某些 MQTT 控制报文包含一个可变报头部分。它在固定报头和负载之间。
可变报头的内容根据报文类型的不同而不同。
可变报头的报文标识符(Packet Identifier)字段存在于多个类型的报文里。
2.4 有效载荷
某些MQTT控制报文在报文的最后部分包含一个有效载荷。对于PUBLISH来说有效载荷就是应用消息。