推荐一款稳定的基于C编写的MQTT Client开源库 cMQTT
MQTT协议详解及开发教程(一)MQTT协议概述
MQTT协议详解及开发教程(二)MQTT服务器EMQx搭建
MQTT协议详解及开发教程(三)MQTT Client工具软件选择及简单测试
MQTT协议详解及开发教程(四)MQTT协议报文格式
前言
在上一篇文章中,我们对MQTT协议的报文格式做了整体的介绍,从本文开始,将通过实例代码,分析MQTT的不同类型的控制报文,我们会使用之前搭建的MQTT服务器和MQTT.fx来进行测试,同时使用Wireshark进行抓包,从最底层字节层面来分析MQTT控制报文。
1.MQTT.fx 发起不含遗嘱的连接
连接成功后,查看Wireshark抓包情况如下:
从上图抓包效果,我们可以看出:
(1) MQTT协议是建立在TCP协议的基础上的应用层协议,也就是说MQTT协议也是TCP协议的一种。
(2)MQTT的CONNECT分2步,client先与server建立TCP连接(3次握手),连接成功后,再进行业务层面的连接。
关于TCP的3次握手连接,本系列文章不再赘述,我们重点分析一下MQTT的connect连接流程
1.1 MQTT Client 发送CONNECT报文抓取
Wireshark分析结果如下:
我们对报文内容进行逐个分析:
1
2
3
4
5// 源码 10 25 00 04 4d 51 54 54 04 c2 00 3c 00 08 63 6c 69 65 6e 74 30 31 00 05 61 64 6d 69 6e 00 08 70 61 73 73 77 6f 72 64
1.1.1 固定报头
0x10 0x25
其中:
0x10–对应的是CONNECT
0x25–剩余长度0x25 = 37个字节。
1.1.2 可变报头
1.1.2.1 协议名
0x00 0x04 0x4d 0x51 0x54 0x54
其中0x00 0x04为协议名称长度–4个字节
0x4d 0x51 0x54 0x54 ,对应的ASCII码为:‘M’, ‘Q’, ‘T’, ‘T’
1.1.2.2 协议等级
0x04 MQTT版本号,04 – v3.1.1
1.1.2.3 连接标志
0xc2
Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
User Name Flag | Password Flag | Will Retain Flag | Will QoS MSB | Will QoS LSB | Will Flag | Clean session | Rreserved | |
1 | 1 | 0 | 0 | 0 | 0 | 1 | 0 |
说明后面跟着数据有 User Name、Password,没有遗嘱设置,选择了清理会话方式与服务器连接。
1.1.2.4 保持连接
0x00 0x3c – 对应十进制 为 60 秒。
保持连接(Keep Alive)是一个以秒为单位的时间间隔,表示16位子,它是指在客户端传输完成一个控制报文的时刻到发送下一个报文的时刻,两者之间允许空闲的最大时间间隔。客户端负责保证控制报文发送的时间间隔不超过保持连接的值。如果没有任何其它的控制报文可以发送,客户端 必须发送一个PINGREQ 报文。
客户端随时可以发送ping指令,服务器如果发现在KeepAalive时间内没有收到客户端的消息,会自动断开与客户端建立的连接。
1.1.2.5 Client ID
00 08 63 6c 69 65 6e 74 30 31
其中:
00 08 – Client ID长度为8个字节
63 6c 69 65 6e 74 30 31 – 对应的ASCII码值为: c l i e n t 0 1
1.1.2.6 User Name
**00 05 61 64 6d 69 6e **
其中:
00 05 – User Name 长度为5个字节
61 64 6d 69 6e – 对应的ASCII码值为: a d m i n
1.1.2.6 Password
00 08 70 61 73 73 77 6f 72 64
其中:
00 08 --Password 长度为5个字节
70 61 73 73 77 6f 72 64 – 对应的ASCII码值为: p a s s w o r d
1.2 MQTT Client 接收到的CONNACK报文抓取
报文源码:
1
220 02 00 00
1.2.1 固定报头
0x20 0x02
其中:
0x20 – 对应的控制包类型为 CONNACK
02 – 剩余字节长度为 2 个字节
1.2.2 可变报头
1.2.2.1 连接确认标志
00
位置:可变报头的第1个字节的第0位
连接确认,具体的内容可以看考MQTT 标准协议.
1.2.2.2 连接返回码
00
位置:可变报头的第2个字节,返回码定义如下:
值 | 返回码响应 | 描述 |
---|---|---|
0 | 0x00连接已接受 | 连接已被服务器接受 |
1 | 0x01连接已拒绝,不支持的协议版本 | 服务器不支持客户端请求的协议版本 |
2 | 0x02连接已拒绝,不合格的客户端ID | 客户端ID是正确的UTF-8码,但服务器不允许使用 |
3 | 0x03连接已拒绝,服务端不可用 | 网络连接已建立,但MQTT服务不可用 |
4 | 0x04连接已拒绝,无效的用户名或密码 | 用户名或密码的数据格式无效 |
5 | 0x05连接已拒绝,未授权 | 客户端未被授权连接到此服务器 |
6-255 | Reserved | 保留 |
1.2.3 有效载荷
CONNACK报文没有有效载荷
2 MQTT Client发送包含 遗嘱 的CONNECT
MQTT Client配置遗嘱LWT如下所示:
2.1 含遗嘱参数的CONNECT 抓包
其中CONNECT报文源码如下:
1
2
3
4
5
610 47 00 04 4d 51 54 54 04 ee 00 3c 00 08 63 6c 69 65 6e 74 30 31 00 11 2f 6f 66 66 6c 69 6e 65 2f 63 6c 69 65 6e 74 30 31 00 0d 64 65 76 69 63 65 20 6f 66 66 69 63 65 00 05 61 64 6d 69 6e 00 08 70 61 73 73 77 6f 72 64
2.1.1 固定报头
0x10 0x47
其中:
0x10–对应的是CONNECT
0x47–剩余长度0x47 = 71个字节。
2.1.2 可变报头
2.1.2.1 协议名
0x00 0x04 0x4d 0x51 0x54 0x54
其中0x00 0x04为协议名称长度–4个字节
0x4d 0x51 0x54 0x54 ,对应的ASCII码为:‘M’, ‘Q’, ‘T’, ‘T’
2.1.2.2 协议等级
0x04 MQTT版本号,04 – v3.1.1
2.1.2.3 连接标志
0xee
Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
User Name Flag | Password Flag | Will Retain Flag | Will QoS MSB | Will QoS LSB | Will Flag | Clean session | Rreserved | |
1 | 1 | 1 | 0 | 1 | 1 | 1 | 0 |
说明后面跟着数据有 User Name、Password,可以看到这里will标志都设置为1.Qos1也设置成了1,
2.1.2.4 保持连接时间
0x00 0x3c – 对应十进制 为 60 秒。
保持连接(Keep Alive)是一个以秒为单位的时间间隔,表示16位子,它是指在客户端传输完成一个控制报文的时刻到发送下一个报文的时刻,两者之间允许空闲的最大时间间隔。客户端负责保证控制报文发送的时间间隔不超过保持连接的值。如果没有任何其它的控制报文可以发送,客户端 必须发送一个PINGREQ 报文。
客户端随时可以发送ping指令,服务器如果发现在KeepAalive时间内没有收到客户端的消息,会自动断开与客户端建立的连接。
2.1.2.5 Client ID
00 08 63 6c 69 65 6e 74 30 31
其中:
00 08 – Client ID长度为8个字节
63 6c 69 65 6e 74 30 31 – 对应的ASCII码值为: c l i e n t 0 1
2.1.2.6 Will Topic
00 11 2f 6f 66 66 6c 69 6e 65 2f 63 6c 69 65 6e 74 30 31
00 11 – Will Topic 长度为17个字节
2f 6f 66 66 6c 69 6e 65 2f 63 6c 69 65 6e 74 30 31 – 对应的ASCII码值为: /offline/client01
2.1.2.7 Will Message
**00 0d 64 65 76 69 63 65 20 6f 66 66 69 63 65 **
其中:
00 0d – Will Message 长度为13个字节
64 65 76 69 63 65 20 6f 66 66 69 63 65 – 对应的ASCII码值为: device office
2.1.2.8 User Name
00 05 61 64 6d 69 6e
其中:
00 05 --User Name长度为5个字节
61 64 6d 69 6e – 对应的ASCII码值为: a d m i n
2.1.2.9 Password
00 08 70 61 73 73 77 6f 72 64
其中:
00 08 --Password 长度为5个字节
70 61 73 73 77 6f 72 64 – 对应的ASCII码值为: p a s s w o r d
2.2 含遗嘱参数的 CONNACK 抓包
报文源码:
1
220 02 00 00
2.2.1 固定报头
0x20 0x02
其中:
0x20 – 对应的控制包类型为 CONNACK
02 – 剩余字节长度为 2 个字节
2.2.2 可变报头
2.2.2.1 连接确认标志
00
位置:可变报头的第1个字节的第0位
连接确认,具体的内容可以看考MQTT 标准协议.
2.2.2.2 连接返回码
00
位置:可变报头的第2个字节,返回码定义如下:
值 | 返回码响应 | 描述 |
---|---|---|
0 | 0x00连接已接受 | 连接已被服务器接受 |
1 | 0x01连接已拒绝,不支持的协议版本 | 服务器不支持客户端请求的协议版本 |
2 | 0x02连接已拒绝,不合格的客户端ID | 客户端ID是正确的UTF-8码,但服务器不允许使用 |
3 | 0x03连接已拒绝,服务端不可用 | 网络连接已建立,但MQTT服务不可用 |
4 | 0x04连接已拒绝,无效的用户名或密码 | 用户名或密码的数据格式无效 |
5 | 0x05连接已拒绝,未授权 | 客户端未被授权连接到此服务器 |
6-255 | Reserved | 保留 |
2.2.3 有效载荷
CONNACK报文没有有效载荷
小结
MQTT协议的CONNECT/CONNACK还是非常标准的。
如果想要设定遗嘱参数,必须要在进行CONNECT之前就将相关参数设定,才能有效。
最后
以上就是超帅鞋子最近收集整理的关于MQTT协议详解及开发教程(五)CONNECT/CONNACK报文分析前言1.MQTT.fx 发起不含遗嘱的连接2 MQTT Client发送包含 遗嘱 的CONNECT小结的全部内容,更多相关MQTT协议详解及开发教程(五)CONNECT/CONNACK报文分析前言1.MQTT.fx内容请搜索靠谱客的其他文章。
发表评论 取消回复