1. MQTT简介
1.1. 介绍
MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议)协议是一种基于发布/订阅(publish/subscribe)模式的“轻量级”通讯协议,该协议构建于TCP/IP协议上,由IBM在1999年发布。MQTT最大优点在于,可以以极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务。做为一种低开销、低带宽占用的即时通讯协议,使其在物联网、小型设备、移动应用等方面有较广泛的应用。
1.2. 特点
MQTT协议运行在TCP/IP或其他网络协议,提供有序、无损、双向连接。其特点包括:
- 使用的发布/订阅消息模式,它提供了一对多消息分发,以实现与应用程序的解耦。
- 对负载内容屏蔽的消息传输机制。
- 对传输消息有三种服务质量(QoS)。
- 数据传输和协议交换的最小化(协议头部只有2字节),以减少网络流量。
- 通知机制,异常中断时通知传输双方。
1.3. MQTT实现原理
MQTT可以理解主要由两端构成网络,一端是服务器端,另一端就是客户端。而客户端又分两个角色,一个是订阅者、另一个是发布者,服务器则是代理,流程如下:
订阅者首先在代理那订阅主题,发布者发布该主题内容时,订阅者才会收到,否则不会接收任何信息。
MQTT本身的消息也分为令部分:主题(Topic)和负载(payload)。
- Topic,可以理解为消息的类型,订阅者订阅(Subscribe)后,就会收到该主题的消息内容(payload)。
- payload,可以理解为消息的内容,是指订阅者具体要使用的内容。
1.4. 服务质量
为了满足不同的场景,MQTT支持三种不同级别的服务质量(Quality of Service,QoS)为不同场景提供消息可靠性。
1.4.1. Qos0
最多一次送达。也就是消息发送的时候,发送端只管发送而不关心接收端是否能接收到,这种服务质量的消息会有一定的丢失,但是能够保证消息的实时性。适合频繁上报的状态类的数据。
1.4.2. Qos1
至少一次送达。也就是消息发送的时候,发送端会等待接收端的一个接收响应,当接收到响应的时候,传输结束。这种服务质量的消息的丢失率要小一些,适合对数据完整性不是很高的场景。
1.4.3. Qos2
准确一次送达。也就是消息发送的时候,发送端会等待接收端的一个接收响应,并且再发送一个确认接收响应,当双端都确认收到报文的时候,传输结束。这种服务质量的消息是不会丢失的。适用指令下行等场景。
1.5. 控制报文格式
控制报文可以分为三个部分组成,分别为:固定报头,可变报头有效载荷部分。
1.5.1. 固定报头
1.5.1.1. 控制报文类型
控制报文的类型:用于标示类型,如:连接(CONNECT)报文,发布(PUBLISH)报文等。他占了四个位。
1.5.1.2. 控制报文类型的标志位
控制报文类型的标志位分别为:标示发送重复数(DUP),服务质量(QoS),保留标志(RETAIN)。同样子他也占了四个位。
1.5.1.3. 剩余长度
从固定报头的第二个字节开始。剩余长度(Remaining Length)表示当前报文剩余部分的字节数,包括可变报头和负载的数据。剩余长度不包括用于编码剩余长度字段本身的字节数。
1.5.2. 可变报头
可变报头,不是一定要存在的。根据不同的类型报文可变报头的内部是会发生改变的。
1.6. 控制报文
1.6.1. CONNECT – 连接服务端
-
固定报头:
- (控制报文类型 + 控制报文类型的标志位)(0x10)+ 剩余长度(等于可变报头的长度(10 字节)加上有效载荷的长度)
-
可变报头:
- 协议名(Protocol Name) + 协议等级(Protocol Level) + 连接标志(Connect Flags) + 保持连接(Keep Alive)
1.7. 抓包分析
1.7.1. CONNECT
102c00044d5154540402003c00206463376562646334333232333463313862613964326262613131653633323738
拆分 | 功能说明 | 备注 |
---|---|---|
102c | 固定报头 | ------ |
10 | 连接服务器的控制报文类型CONNECT | 高4位,后4位为保留位 |
2c | 剩余长度 1 个字节 | 44 (可变报头的长度 + 有效载荷的长度) |
00044d5154540402003c | 可变报头 | ------ |
0004 | 长度 | ------ |
4d515454 | MQTT | ------ |
04 | 协议等级 | 表示3.1.1版本 |
02 | 连接标志 | Will Flag = 1 |
003c | 保持连接 | Keep Alive = 30s |
00206463376562646334333232333463313862613964326262613131653633323738 | 有效载荷 | ------ |
0020 | 有效载荷客户端标识符长度 | ------ |
6463376562646334333232333463313862613964326262613131653633323738 | 有效载荷客户端标识符 16进制表示 | dc7ebdc432234c18ba9d2bba11e63278 |
1.7.2. CONNACK
20020000
拆分 | 功能说明 | 备注 |
---|---|---|
2002 | 固定报头 | ------ |
20 | CONNACK控制报文类型CONNACK | 高4位,后4位为保留位 |
02 | 剩余长度 | 对于 CONNACK 报文数值固定是 2 |
0000 | 可变报头 | ------ |
00 | 连接确认标志 | 对于 CONNACK 报文数值固定是 2 |
00 | 连接返回码 | 00 表示 连接已经接受 |
------ | CONNACK 报文没有有效载荷 | ------ |
1.7.3. 设置遗嘱消息的CONNECT报文
105600044d5154540426003c00206463376562646334333232333463313862613964326262613131653633323738000f746573745f77696c6c5f746f7069630017746573745f77696c6c5f746f7069635f6d657373616765
拆分 | 功能说明 | 备注 |
---|---|---|
1056 | 固定报头 | ------ |
10 | 连接服务器的控制报文类型CONNECT | 高4位,后4位为保留位 |
56 | 剩余长度 1 个字节 | 44 (可变报头的长度 + 有效载荷的长度) |
00044d5154540402003c | 可变报头 | ------ |
0004 | 长度 | ------ |
4d515454 | MQTT | ------ |
04 | 协议等级 | 表示3.1.1版本 |
26 | 连接标志 | Will RETAIN = 1,Will Flag = 1,Clean Session = 1 |
003c | 保持连接 | Keep Alive = 60s |
00206463376562646334333232333463313862613964326262613131653633323738000f746573745f77696c6c5f746f7069630017746573745f77696c6c5f746f7069635f6d657373616765 | 有效载荷 | ------ |
0020 | 有效载荷客户端标识符长度 | 32个字节 |
6463376562646334333232333463313862613964326262613131653633323738 | 有效载荷客户端标识符 16进制表示 | dc7ebdc432234c18ba9d2bba11e63278 |
000f746573745f77696c6c5f746f706963 | 遗嘱主题 | ------ |
000f | 遗嘱主题长度 | 16个字节 |
746573745f77696c6c5f746f706963 | 遗嘱主题内容 | test_will_topic |
0017746573745f77696c6c5f746f7069635f6d657373616765 | 遗嘱主题消息 | ------ |
0017 | 遗嘱主题消息长度 | 23个字节 |
746573745f77696c6c5f746f7069635f6d657373616765 | 遗嘱主题消息 | test_will_topic_message |
1.7.4. DISCONNECT
e000
拆分 | 功能说明 | 备注 |
---|---|---|
e000 | 固定报头 | 1、DISCONNECT 没有可变报头,没有有效载荷,只有固定报头。2、服务器不需要回复报文。 |
1.7.5. QoS 为0的PUBLISH 报文
301b000c746573745f7075626c697368746573745f3132333435363738
拆分 | 功能说明 | 备注 |
---|---|---|
301b | 固定报头 | ------ |
30 | PUBLISH 控制报文类型 | DUP(重发标志(DUP)为0,服务质量(QoS)标志为0,保留标志(RETAIN)为0) |
1b | 剩余长度 1 个字节 | 27 (可变报头的长度 + 有效载荷的长度) |
000c746573745f7075626c697368 | 可变报头 | ------ |
000c | 可变报头长度 | 12个字节 |
746573745f7075626c697368 | topic名称 | test_publish |
746573745f3132333435363738 | 有效载荷 | test_12345678 |
1.7.6. PUBLISH —> PUBACK
1.7.6.1. QoS 为1的PUBLISH报文
3222000c746573745f7075626c6973680001746573745f31323334353637385f716f7331
拆分 | 功能说明 | 备注 |
---|---|---|
3222 | 固定报头 | ------ |
32 | PUBLISH 控制报文类型 | DUP(重发标志(DUP)为0,服务质量(QoS)标志为1(至少分发一次),保留标志(RETAIN)为0) |
22 | 剩余长度 1 个字节 | 34 (可变报头的长度 + 有效载荷的长度) |
000c746573745f7075626c6973680001 | 可变报头 | ------ |
000c | 可变报头长度 | 12个字节 |
746573745f7075626c697368 | topic名称 | test_publish |
0001 | 报文标识符 | 1.客户端每次发送一个新的特殊的控制报文时都必须分配一个当前为使用的报文标识符。2.如果一个客户端要重发这个特殊的控制报文,在随后重发那个报文时,它必须使用相同的标志符。3.只有当客户端处理完这个报文对应的确认后,这个报文标识符就释放可重用。4.只有当 QoS 等级是 1 或 2 时,报文标识符字段才能出现在 PUBLISH 报文中。 |
746573745f31323334353637385f716f7331 | 有效载荷 | test_12345678_qos1 |
1.7.6.2. PUBACK
40020001
拆分 | 功能说明 | 备注 |
---|---|---|
4002 | 固定报头 | ------ |
40 | PUBACK 控制报文类型 | ------ |
02 | 剩余长度 1 个字节 | 固定为2 (可变报头的长度) |
0001 | 可变报头 | 1.包含等待确认的 PUBLISH 报文的报文标识符2.PUBACK报文没有有效载荷 |
1.7.7. PUBLISH —> PUBREC —> PUBREL —> PUBCOMP
1.7.7.1. QoS 为2的PUBLISH报文
3422000c746573745f7075626c6973680002746573745f31323334353637385f716f7332
拆分 | 功能说明 | 备注 |
---|---|---|
3422 | 固定报头 | ------ |
34 | PUBLISH 控制报文类型 | DUP(重发标志(DUP)为0,服务质量(QoS)标志为2(仅分发一次),保留标志(RETAIN)为0) |
22 | 剩余长度 1 个字节 | 34 (可变报头的长度 + 有效载荷的长度) |
000c746573745f7075626c6973680002 | 可变报头 | ------ |
000c | 可变报头长度 | 12个字节 |
746573745f7075626c697368 | topic名称 | test_publish |
0002 | 报文标识符 | 1.只有当 QoS 等级是 1 或 2 时,报文标识符字段才能出现在 PUBLISH 报文中。 |
746573745f31323334353637385f716f7332 | 有效载荷 | test_12345678_qos2 |
1.7.7.2. PUBREC
50020002
拆分 | 功能说明 | 备注 |
---|---|---|
5002 | 固定报头 | ------ |
50 | PUBREC 控制报文类型 | ------ |
02 | 剩余长度 1 个字节 | 固定为2 (可变报头的长度) |
0002 | 可变报头 | 1.PUBREC 报文是对 QoS 等级 2 的 PUBLISH 报文的响应。2.它是 QoS 2 等级协议交换的第二个报文。2.PUBREC报文没有有效载荷。 |
1.7.7.3. PUBREL
62020002
拆分 | 功能说明 | 备注 |
---|---|---|
5002 | 固定报头 | ------ |
62 | PUBREL 控制报文类型 | ------ |
02 | 剩余长度 1 个字节 | 固定为2 (可变报头的长度) |
0002 | 可变报头 | 1.PUBREL 报文是对 PUBREC 报文的响应。2.它是 QoS 2 等级协议交换的第三个报文。 2.PUBREL报文没有有效载荷。 |
1.7.7.4. PUBCOMP
70020002
拆分 | 功能说明 | 备注 |
---|---|---|
5002 | 固定报头 | ------ |
70 | PUBCOMP 控制报文类型 | DUP(重发标志(DUP)为0,服务质量(QoS)标志为2(至少分发一次),保留标志(RETAIN)为0) |
02 | 剩余长度 1 个字节 | 固定为2 (可变报头的长度 + 有效载荷的长度) |
0002 | 可变报头 | 1.PUBCOMP 报文是对 PUBREL 报文的响应。2.它是 QoS 2 等级协议交换的第四个也是最后一个报文。 3.PUBCOMP报文没有有效载荷。 |