在“[3] MQTT,mosquitto,Eclipse Paho---如何使用 Eclipse Paho MQTT工具来发送订阅MQTT消息?”一文中我已经和大家简单讲述了如何使用Eclipse Paho MQTT。那么当我们点击“Connect”按钮,究竟在TCP协议层发生了什么?如何通过MQTT规定的协议和TCP的二进制数据进行对比,从而更加深入的学习MQTT的消息格式呢?笔者将带领大家以CONNECT消息格式为例子,分析第一个MQTT的消息格式, MQTT的CONNECT消息主要用来在客户端和服务端建立一个TCP的通信连接,这个CONNECT的发起者肯定是客户端。因为要建立一个连接,所以客户端在这个消息里面需要提供Client ID, 如果服务端设置了用户名和密码认证,在这个消息里面必须还要包括用户名和密码的相关信息,另外如果设置了连接断开的最后遗言(Last Will and Tesament),则在这个消息里面还必须包含和最后遗言相关的信息。
首先,在本实例中,用于连接MQTT服务器的相关配置信息如下,请大家记住下面的用于建立MQTT连接的相关信息。
同时假设大家都已经从下面的地址下载并安装了WireShark(https://www.wireshark.org/download.html)
顺便说一下,在Wireshark中,分为capture filter和Display Filer,我们只需要在WireShark软件中的capture filter 输入下面的过滤条件,则与MQTT服务交互的相关TCP的数据包就能抓取到。如下图所示意.
这个时候,我们先启动WireShark,然后点击Eclipse Paho MQTT工具的“Connect”,这个时候WireShark就能抓取下面的TCP数据包。具体的包如下:
注意当前实现的是v3.1.1的协议,请参考下面的文档
http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718029
(1) 固定头部(Fix head): 16进制的数据:10 1e
表1. CONNECT 报文的固定头部(Fixed Header)格式
Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
byte 1 | MQTT Control Packet type (1) | Reserved | ||||||
0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | |
byte 2… | Remaining Length |
10---表示发送的Connect的请求
4e---表示后面将跟着4*16+14=78个字节,这个表示剩下的78个字节,不但包括可变头部(规定是10个字节)还包括
68个负载的字节(payload)
2.可变头部的10个字节
2.1 协议字节:16进制数据为:00 04 4d 51 54 54
表2. 协议名称字节格式
Description | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
Protocol Name | |||||||||
byte 1 | Length MSB (0) | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
byte 2 | Length LSB (4) | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
byte 3 | ‘M’ | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 1 |
byte 4 | ‘Q’ | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 1 |
byte 5 | ‘T’ | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 0 |
byte 6 | ‘T’ | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 0 |
00 MSB(0)
04 LSB(4)
4d M
51 Q
54 T
54 T
2.2 协议级别: 16进制数据为:04
表3. 协议版本信息表:
Description | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
Protocol Level | |||||||||
byte 7 | Level(4) | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
04 代表的是3.1.1的协议
2.3 连接信息标志位,16进制数据为:ee
表4 - 连接标志位(Connect Flag bits)
Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
User Name Flag | Password Flag | Will Retain | Will QoS | Will Flag | Clean Session | Reserved | ||
byte 8 | X | X | X | X | X | X | X | 0 |
ee 代表连接的flag,1110 1110-- username(1) password(1) Will Retain(1) Will QoS(01), Will(1), Clean session(1) not used(0)
2.4 心跳信息间隔,16进制数据为:00 3c
表5. 心跳时间间隔(Keep Alive)
Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
byte 9 | Keep Alive MSB | |||||||
byte 10 | Keep Alive LSB |
00 Keep alive的时间的高位(MSB):0
3c 代表Keep alive时间的低位(LSB): 3*16+12=60
3 分隔标志: 16进制数据为:00 1e
4.客户端ID: 16进制数据为:31 31 31 31 31 31 31 31 31 31 31 31 31 31 3131 31 31 31 31 31 31 31 31 31 31 31 31 31 31
后面的30个字节代表的是clientID(如果Will 为0,没有设置;且用户名和密码也为空,所以后面的payload里面就没有其他的信息了)
111111111111111111111111111111
5. 分隔标志: 16进制数据为:00 3c
6. Will Topic: 16进制数据为:6c 77 74
6c 77 74代表的ASCII码就是: lwt
7.分隔标志: 16进制数据为:00 0c
8. Will Message: 16进制数据为:48 65 6c 6c 6f 20 57 6f 72 6c 64 21
48 65 6c 6c 6f 20 57 6f 72 6c 64 21 代表的ASCII码就是最后遗言(Last Will Message: Hello World!
9. 分隔标志: 00 05
10. 连接的用户名(Username): 16进制数据为:61 64 6d 69 6e
61 64 6d 69 6e 代表的ASCII码就是用户名:admin
11. 分隔标志: 00 08
12. 连接的密码Password: 16进制数据为: 70 6173 73 77 6f 72 64
70 6173 73 77 6f 72 64 代表的ASCII码就是用户名 :password
恭喜你,整个的Connect的消息格式就分析完毕了。按赖不住激动心情的你,是不是想跃跃欲试了!
下一个章节,我们将会给大家继续分享ConnAck消息格式,这个消息格式相对来说比较简单和轻松,敬请期待,谢谢.