1. 报文
固定报文格式:类型+标志位
| Bit |
7 - 4 |
3 - 0 |
| byte 1 |
MQTT控制报文的类型 |
用于指定控制报文类型的标志位 |
| byte 2... |
剩余长度 |
1.1 MQTT控制报文的类型:
| 报文类型 |
字段值 |
数据方向 |
描述 |
| 保留 |
0 |
禁用 |
保留 |
| CONNECT |
1 |
Client ---> Server |
客户端连接到服务器 |
| CONNACK |
2 |
Server ---> Client |
连接确认 |
| PUBLISH |
3 |
Client <--> Server |
发布消息 |
| PUBACK |
4 |
Client <--> Server |
发布确认 |
| PUBREC |
5 |
Client <--> Server |
消息已接收(QoS2第一阶段) |
| PUBREL |
6 |
Client <--> Server |
消息释放(QoS2第二阶段) |
| PUBCOMP |
7 |
Client <--> Server |
发布结束(QoS2第三阶段) |
| SUBSCRIBE |
8 |
Client ---> Server |
客户端订阅请求 |
| SUBACK |
9 |
Server ---> Client |
服务端订阅确认 |
| UNSUBACRIBE |
10 |
Client ---> Server |
客户端取消订阅 |
| UNSUBACK |
11 |
Server ---> Client |
服务端取消订阅确认 |
| PINGREQ |
12 |
Client ---> Server |
客户端发送心跳 |
| PINGRESP |
13 |
Server ---> Client |
服务端回复心跳 |
| DISCONNECT |
14 |
Client ---> Server |
客户端断开连接请求 |
| 保留 |
15 |
禁用 |
保留 |
1.2 控制报文类型的标志位:
| 控制报文 |
固定报头标志 |
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 |
DUP |
QoS |
QoS |
RETAIN |
| PUBACK |
Reserved |
0 |
0 |
0 |
0 |
| PUBREC |
Reserved |
0 |
0 |
0 |
0 |
| PUBREL |
Reserved |
0 |
0 |
1 |
0 |
| PUBCOMP |
Reserved |
0 |
0 |
0 |
0 |
| SUBSCRIBE |
Reserved |
0 |
0 |
1 |
0 |
| SUBACK |
Reserved |
0 |
0 |
0 |
0 |
| UNSUBSCRIBE |
Reserved |
0 |
0 |
1 |
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 |
- 看上面的消息可以观察到PUB的QOS标志直接位于“控制报文类型的标志位”里面,而CONNECT和SUB的QOS标记却不在头部。
- 抓包可以发现CONNECT和SUB的QOS标记位于后续的数据里面
- PING心跳没有QOS设置
2. 连接
| 报文类型 |
数据方向 |
描述 |
| 0x10 |
client->broker |
MQTT CONNECT |
| 0x20 |
broker->client |
MQTT CONNACK |
| 值 |
返回码响应 |
描述 |
| 0 |
0x00连接已接受 |
连接已被服务端接受 |
| 1 |
0x01连接已拒绝,不支持的协议版本 |
服务端不支持客户端请求的MQTT协议级别 |
| 2 |
0x02连接已拒绝,不合格的客户端标识符 |
客户端标识符是正确的UTF-8编码,但服务端不允许使用 |
| 3 |
0x03连接已拒绝,服务端不可用 |
网络连接已建立,但MQTT服务不可用 |
| 4 |
0x04连接已拒绝,无效的用户名或密码 |
用户名或密码的数据格式无效 |
| 5 |
0x05连接已拒绝,未授权 |
客户端未被授权连接到此服务器 |
| 6-255 |
保留 |
如果认为上表中的所有连接返回码都不太合适,那么服务端必须 |
3. 心跳
一个心跳有三个包
| 报文类型 |
数据方向 |
描述 |
| 0xc0 |
client->broker |
MQTT PINGREQ |
| 0xd0 |
broker->client |
MQTT PINGRESP |
| client->broker |
TCP ACK |
4. 发布
4.1 QOS=0时
| 报文类型 |
数据方向 |
描述 |
| 0x30 |
client->broker |
MQTT PUBLISH |
| broker->client |
TCP ACK |
4.2 QOS=1时
| 报文类型 |
数据方向 |
描述 |
| 0x32 |
client->broker |
MQTT PUBLISH |
| 0x40 |
broker->client |
MQTT PUBACK |
4.3 QOS=2时
| 报文类型 |
数据方向 |
描述 |
| 0x34 |
client->broker |
MQTT PUBLISH |
| 0x50 |
broker->client |
MQTT PUBREC |
| 0x62 |
client->broker |
MQTT PUBREL |
| 0x70 |
broker->client |
TCP PUBCOMP |
5. 抓包
【MQTT】使用Wireshark分析MQTT协议:
https://blog.csdn.net/yannanxiu/article/details/71310723
- 更新到最新的版本可以可以直接解析mqtt的报文(必须是1883端口的才可以解析)
- 但是还是没办法解析mqtts的报文,会显示BitTorrent(比特流)
- 可以用端口过滤
(tcp.dstport == 1883) || (tcp.srcport == 1883)
http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/mqtt-v3.1.1.html
https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html