MQTT协议总结

MQTT协议总结

报文基础结构

报文组成是否可选
固定报文头固定存在
可变报文头可选
有效荷载可选

固定报文头

每个MQTT报文都包含固定报文头

固定报文头字节索引高低位作用
报文类型1命令的种类(共16种,0~15)
标志位1命令的具体行为特征
长度2-5可变高8位为0时不往下读取

可变头

包含每个报文的上下文信息,每个报文类型的可变头内容和长度都不同,后面在介绍报文的时候一起总结

荷载

用于传递报文真正的业务数据,同样每个报文类型的荷载数据各不相同,后面在介绍报文的时候一起总结

QoS

Qos 分为 3个等级 0、1、2
0等级:生产者发送数据后,无需接收响应,无重传机制
1等级:生产者发送数据后,需要一次响应,有重传机制
2等级:生产者发送数据后,需要交互两次,有重传机制

报文类型整理

链接与断开
标志位序号16进制序号命令名称方向作用
10x1CONNECT客户端->服务器发起TCP连接后的第一个报文,携带ClientID、账号密码、心跳时间
20x2CONNACK服务端->客户端服务端对CONNECT的回应,告诉你“连上了”或“密码错误”
140xEDISCONNECT双向优雅地断开连接,通知Broker“我要下线了,别等我心跳了
CONNECT真实报文
10 1D 00 04 4D 51 54 54 04 C2 00 3C 00 04 74 65 73 74 00 05 61 64 6D 69 6E 00 04 70 61 73 73
字段名称字节范围内容所属部分作用
报文类型+标志位110固定头CONNECT
长度21D固定头剩余长度 = 29
协议名3-800 04 4D 51 54 54可变头两字节长度 4字节“MQTT”固定标识
协议级别904可变头用的是3.1.1 (0x04) 还是5.0 (0x05)
连接标识10C2可变头可变头控制是否带密码、是否清理会话、是否有遗嘱
保活时间11-1200 3C可变头超过多少秒没发数据,可以踢
ClinetID13-1800 04 74 65 73 74有效荷载(2字节长度 + ID)这里是test
用户名19-2500 05 61 64 6D 69 6E有效荷载(2字节长度 + 用户名)这里是admin
密码26-3000 04 70 61 73 73有效荷载(2字节长度 + 密码)这里是pass
连接标识的意义

0xC2
11 00 001 0
││││ │││└─ Bit 0: Reserved = 0
││││ ││└── Bit 1: Clean Session = 1 → 清理会话
││││ │└─── Bit 2: Will Flag = 0 → 无遗嘱
││││ └──── Bit 3: Will QoS bit0 = 0 ┐
│││└────── Bit 4: Will QoS bit1 = 0 ┘ → QoS = 0
││└─────── Bit 5: Will Retain = 0 → 无效
│└──────── Bit 6: Password Flag = 1 → 有密码
└───────── Bit 7: User Name Flag = 1 → 有用户名

CONNACK 真实报文
20 02 01 00
字段名称字节范围内容所属部分作用
报文类型+标志位120固定头CONNACK
长度202固定头剩余长度 = 2
连接标识301可变头连接返回码
连接返回码400可变头
连接返回码如下:

0x00 连接已接受
0x01 拒绝:不支持的协议版本
0x02 拒绝:无效的客户端标识符
0x03 拒绝:服务端不可用
0x04 拒绝:用户名或密码错误
0x05 拒绝:未授权
Session Present位
只有 Clean Session = 0(不清理会话)时,这个位才有意义。
如果 Clean Session = 1,服务端必须将此位置 0。

DISCONNECT 真实报文
E0 00
字段名称字节范围内容所属部分作用
报文类型+标志位1E0固定头DISCONNECT
长度200固定头剩余长度 = 0

消息发布流转

标志位序号16进制序号命令名称方向作用
30x30PUBLISH双向真正的消息载体。生产者发它给Broker,Broker也发它给消费者
40x40PUBACK双向QoS 1专用。接收方说:我已收到这条消息(QoS 1),不用重发了
50x50PUBREC双向QoS 2专用(第1步)。接收方说:我收到你的QoS 2消息了
60x60PUBREL双向QoS 2专用(第2步)。发送方说:好的,那你把这条消息释放给消费者吧
70x60PUBCOMP双向QoS 2专用(第3步)。接收方说:我已经处理完了,这事彻底了结
PUBLISH 真实报文(生产者向代理发送数据、代理发向消费者)
3A 11 00 0B 73 65 6E 73 6F 72 2F 74 65 6D 70 00 01 32 35 2E 36
字段名称字节范围内容所属部分作用
报文类型1(高4位)0x3固定头PUBLISH
标志位1(低4位)0xA固定头DUP (重发标识)、QoS bit1、QoS bit0、Retain(保留标志)
长度211固定头长度= 17
主题长度3-400 0B可变头主题名长度= 11字节
主题名5-1573 65 6E 73 6F 72 2F 74 65 6D 70可变头sensor/temp
报文标识符16-1700 01Packet ID (QoS>0时必须)
数据内容18-2132 35 2E 36有效荷载生产者发送的数据 26.5
PUBACK 真实报文(代理回复生产者、消费者回复代理)

只有QoS 1 需要 PUBACK

40 02 00 01
字段名称字节范围内容所属部分作用
报文类型+标志位10x40固定头PUBACK
长度20x02固定头长度=2字节
报文标识符3-42可变头Packet ID (QoS>0时必须)
PUBREC 真实报文

只有QoS 2 需要 PUBREC

50 02 00 01
字段名称字节范围内容所属部分作用
报文类型+标志位10x50固定头PUBREC
长度20x02固定头长度=2字节
报文标识符3-42可变头Packet ID (QoS>·1时必须)
PUBREL 真实报文

只有QoS 2 需要 PUBREL

62 02 00 01
字段名称字节范围内容所属部分作用
报文类型+标志位10x62 固定头PUBREL
长度20x02固定头长度=2字节
报文标识符3-42可变头Packet ID (QoS>·1时必须)
PUBCOMP 真实报文

只有QoS 2 需要 PUBCOMP

70 02 00 01
字段名称字节范围内容所属部分作用
报文类型+标志位10x70 固定头PUBCOMP
长度20x02固定头长度=2字节
报文标识符3-42可变头Packet ID (QoS>·1时必须)

订阅与取消订阅

标志位序号16进制序号命令名称方向作用
80x8SUBSCRIBE客户端->服务端客户端发起订阅请求
90x9SUBACK服务端->客户端服务端回应订阅
100xAUNSUBSCRIBE客户端->服务端客户端发起取消订阅
110xBUNSUBACK服务端->客户端服务端回应取消
SUBSCRIBE 真实报文
82 17 00 01 00 0B 73 65 6E 73 6F 72 2F 74 65 6D 70 01 00 05 63 6D 64 2F 23 00
字段名称字节范围内容所属部分作用
报文类型+ 标志位10x82固定头SUBSCRIBE
长度20x17固定头剩余长度 = 23
包ID3-400 01可变头Packet ID = 1
主题1长度5-600 0B有效荷载主题长度 = 11
主题1名7-1773 65 6E 73 6F 72 2F 74 65 6D 70有效荷载“sensor/temp”
主题1的QoS等级1801有效荷载主题1的QoS等级 = 1
主题2长度19-2000 05有效荷载主题2的长度
主题2名21-2563 6D 64 2F 23有效荷载主题2名称 = cmd/#
主题2QoS等级2600有效荷载主题2的QoS等级 = 0
SUBACK真实报文
90 04 00 01 01 00
字段名称字节范围内容所属部分作用
报文类型+ 标志位10x90固定头SUBACK
长度 20x4固定头剩余长度= 4
长度20x17固定头剩余长度 = 23
包ID3-400 01可变头Packet ID = 1
主题1返回501有效荷载主题1返回码:QoS 1 授予
主题2返回600有效荷载主题1返回码:QoS 2 授予

其中主题返回有4种情况

含义
0x00QoS 0 成功
0x01QoS 1 成功
0x02QoS 2 成功
0x80失败(被拒绝)
UNSUBSCRIBE 真实报文
A2 0E 00 02 00 0B 73 65 6E 73 6F 72 2F 74 65 6D 70
字段名称字节范围内容所属部分作用
报文类型+标志位10xA2固定头UNSUBSCRIBE
长度20x0E固定头剩余长度 = 14
包ID3-400 02可变头Packet ID = 2
主题1长度5-600 0B有效荷载主题长度 = 11
主题1名7-1773 65 6E 73 6F 72 2F 74 65 6D 70有效荷载“sensor/temp”
UNSUBACK 真实报文
B0 02 00 02
字段名称字节范围内容所属部分作用
报文类型+ 标志位10xB0固定头UNSUBACK
长度20x02固定头剩余长度 = 2
包ID3-400 02可变头Packet ID = 2

心跳保活

PINGREQ 真实报文(客户端->服务端)
C0 00
字段名称字节范围内容所属部分作用
报文类型+ 标志位10xC0固定头PINGREQ
长度20x00固定头剩余长度 = 0
PINGRESP (服务端->客户端)
D0 00
字段名称字节范围内容所属部分作用
报文类型+ 标志位10xD0固定头PINGRESP
长度20x00固定头剩余长度 = 0