在“[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消息格式,这个消息格式相对来说比较简单和轻松,敬请期待,谢谢.