mqtt 报文_报文怎么解析

(4) 2024-06-05 12:12

Hi,大家好,我是编程小6,很荣幸遇见你,我把这些年在开发过程中遇到的问题或想法写出来,今天说一说mqtt 报文_报文怎么解析,希望能够帮助你!!!。

文章目录

      • 一、报文结构
      • 二、固定报头
      • 三、剩余长度
      • 四、mqtt控制报文
        • Ⅰ、CONNECT
          • 1、固定报头
          • 2、 可变报头
            • 2.1、协议名
            • 2.2、协议级别
            • 2.3、连接标志
            • 2.4 保持连接
            • 2.5、可变报头示例
          • 3、有效载荷
            • 3.1、 客户端标识符
            • 3.2、遗嘱主题
            • 3.3、 遗嘱消息
            • 3.4、 用户名
            • 3.5、 密码
      • 五、报文分析

对 mqtt 是做什么还不知道,怎么简单使用还不知道的可以查看我的其他博客,以下对 mqtt 报文做简单分析

一、报文结构

表格1.1-报文结构

Fixed header 固定报头,所有控制报文都包含
Variable header 可变报头,部分控制报文包含
Payload 有效载荷,部分控制报文包含
mqtt 报文结构 = 固定报头 + 可变报头 + 有效载荷

二、固定报头

表格2.1-固定报头格式

Bit 7 6 5 4 3 2 1 0
byte1 MQTT控制报文类型 用于指定控制报文类型的控制位
byte2 剩余长度

表格2.2-mqtt 控制报文类型(即表格2.1-固定报头中 4~7位置)

名字 报文流动方向 描述
Reserved 0 禁止 保留
CONNECT 1 客户端到服务端 客户端请求连接服务端
CONNACK 2 服务端到客户端 连接报文确认
PUBLISH 3 两个方向都允许 发布消息
PUBACK 4 两个方向都允许 QoS 1 消息发布收到确认
PUBREC 5 两个方向都允许 发布收到(保证交付第一步)
PUBREL 6 两个方向都允许 发布释放(保证交付第二步 )
PUBCOMP 7 两个方向都允许 QoS 2 消息发布完成(保证交互第三步)
SUBSCRIBE 8 客户端到服务端 客户端订阅请求
SUBACK 9 服务端到客户端 订阅请求报文确认
UNSUBSCRIBE 10 客户端到服务端 客户端取消订阅请求
UNSUBACK 11 服务端到客户端 取消订阅报文确认
PINGREQ 12 客户端到服务端 心跳请求
PINGRESP 13 服务端到客户端 心跳响应
DISCONNECT 14 客户端到服务端 客户端断开连接
Reserved 15 禁止 保留

表格 2.3 -标志位 (即表格2.1-固定报头 0~3位置)

控制报文 固定报头标志 Bit3 Bit2 Bit1 Bit0
CONNECT Reserved 0 0 0 0
CONNACK Reserved 0 0 0 0
PUBLISH Used in MQTT 3.1.1 DUP1 QoS2 QoS2 RETAIN3
PUBACK Reserved 0 0 0 0
PUBREC Reserved 0 0 0 0
PUBREL Reserved 0 0 1 0
PUBCOMP Reserved 0 0 0 0
SUBSCRIBE Reserved 0 0 1 0
SUBACK Reserved 0 0 0 0
UNSUBSCRIBE Reserved 0 0 1 0
UNSUBACK Reserved 0 0 0 0
PINGREQ Reserved 0 v0 0 0
PINGRESP Reserved 0 0 0 0
DISCONNECT Reserved 0 0 0 0

DUP1 =控制报文的重复分发标志

QoS2 = PUBLISH 报文的服务质量等级

RETAIN3 = PUBLISH 报文的保留标志

三、剩余长度

位置:从第 2 个字节开始。

包括可变报头和负载的数据,变长度编码方案,每个字节可以编码 128 个数值和一个延续位,剩余长度字段最大 4 个字节,注意最高位为 1 表示后面至少还有一个字节,这允许应用发送最大 256MB(268,435,455) 大小的控制报文。这个数值在报文中的表示是:0xFF,0xFF,0xFF,0x7F

表格3.1-报文标识符字段                                                                                 表格3.2-有效载荷

控制报文 报文标识符字段 控制报文 有效载荷
CONNECT 不需要 CONNECT 需要
CONNACK 不需要 CONNACK 不需要
PUBLISH 需要 (如果 QoS > 0) PUBLISH 可选
PUBACK 需要 PUBACK 不需要
PUBREC 需要 PUBREC 不需要
PUBREL 需要 PUBREL 不需要
PUBCOMP 需要 PUBCOMP 不需要
SUBSCRIBE 需要 SUBSCRIBE 需要
SUBACK 需要 SUBACK 需要
UNSUBSCRIBE 需要 UNSUBSCRIBE 需要
UNSUBACK 需要 UNSUBACK 不需要
PINGREQ 不需要 PINGREQ 不需要
PINGRESP 不需要 PINGRESP 不需要
DISCONNECT 不需要 DISCONNECT 不需要

四、mqtt控制报文

Ⅰ、CONNECT

客户端到服务端的网络连接建立后,客户端发送给服务端的第一个报文必须是 CONNECT 报文在一个网络连接上,客户端只能发送一次 CONNECT 报文。服务端必须将客户端发送的第二个 CONNECT 报文当作协议违规处理并断开客户端的连接。

1、固定报头

表格4.1-固定报头

Bit 7 6 5 4 3 2 1 0
byte1 MQTT报文类型(1) Reserved 保留位
0 0 0 1 0 0 0 0
byte2 剩余长度

根据 表格2.2-mqtt 控制报文类型 和 表格 2.3 -标志位 查询数据

2、 可变报头

某些 MQTT 控制报文包含一个可变报头部分。它在固定报头和负载之间。可变报头的内容根据报文类型的不同而不同。可变报头的报文标识符(Packet Identifier)字段存在于在多个类型的报文里。如:CONNECT 报文的可变报头按下列次序包含四个字段:协议名(Protocol Name),协议级别(Protocol Level),连接标志(ConnectFlags)和保持连接(Keep Alive)。不同控制报文可变头部不同

2.1、协议名

表格4.2-协议名

说明 7 6 5 4 3 2 1 0
协议名
byte1 长度 MSB (0) 协议长度 0 0 0 0 0 0 0 0
bytE2 长度 LSB (4) 协议长度 0 0 0 0 0 1 0 0
byte3 ‘M’ 0 1 0 0 1 1 0 1
byte4 'Q' 0 1 0 1 0 0 0 1
byte5 'T' 0 1 0 1 0 1 0 0
byte6 'T' 0 1 0 1 0 1 0 0
2.2、协议级别

表格4.3-协议级别

说明 7 6 5 4 3 2 1 0
协议级别
byte7 Level(4) 0 0 0 0 0 1 0 0

Level(4) 为mqtt 3.1.1 版协议,协议级别字段的值是 4(0x04)。

2.3、连接标志

连接标志字节包含一些用于指定 MQTT 连接行为的参数。它还指出有效载荷中的字段是否存在。

表格4.4-连接标志位

Bit 7 6 5 4 3 2 1 0
User Name Flag Password Flag Will Retain Will QoS Will Flag Clean Session Reserved
Level(4) x x x x x x x 0

服务端必须验证 CONNECT 控制报文的保留标志位(第 0 位)是否为 0,如果不为 0 必须断开客户端 连接。Reserved 为以保留。

2.3.1、CleanSession

第一位CleanSession指定了会话状态的处理方式,控制会话状态生存时间,0代表保留会话,当连接断开后,客户端和服务端

必须保存会话信息,QoS 1 和 QoS 2 级别的消息保存为会话状态的一部分,服务端也可以保存满足相同条件的 QoS 0 级别的

消息。1代表清除会话,不保留离线消息,重连会建立新的会话。

2.3.2、遗嘱标志

位置:连接标志的第 2 位。

遗嘱标志(Will Flag)被设置为 1,表示如果连接请求被接受了,遗嘱(Will Message)消息必须被存储在 服务端并

且与这个网络连接关联。之后网络连接关闭时,服务端必须发布这个遗嘱消息,除非服务端收到 DISCONNECT 报文时删除了这个遗嘱消息

遗嘱消息发布的条件,包括但不限于: •

  • 服务端检测到了一个 I/O 错误或者网络故障。 •

  • 客户端在保持连接(Keep Alive)的时间内未能通讯。 •

  • 客户端没有先发送 DISCONNECT 报文直接关闭了网络连接。 •

  • 由于协议错误服务端关闭了网络连接。

遗嘱消息连接标志位 WILL QOSWILL RETAIN 字段会被服务端用到,同时有效载荷中必须包含 WILL TOPIC

WILL MESSAGE 字段,遗嘱标志被设置为 0,连接标志中的 WILL QOS 和 WILL RETAIN 字段必须设置为 0,并

且有效载荷中不能 包含 WILL TOPIC 和 WILL MESSAGE 字段

2.3.3、遗嘱Qos

位置:连接标志的第 4 和第 3 位。

如果遗嘱标志被设置为 0,遗嘱 QoS 也必须设置为 0。

如果遗嘱标志被设置为 1,遗嘱 QoS 的值可以等于 0,1,2。

2.3.3、遗嘱保留

位置:连接标志的第 5 位。

如果遗嘱标志(Will Flag)被设置为 0,遗嘱保留(Will Retain)标志也必须设置为 0。

如果遗嘱标志(Will Flag)被设置为 1:

  • 如果遗嘱保留被设置为 0,服务端必须将遗嘱消息当作非保留消息发布。

  • 如果遗嘱保留被设置为 1,服务端必须将遗嘱消息当作保留消息发布

2.3.4 、用户名标志

位置:连接标志的第 7 位。

如果用户名(User Name)标志被设置为 0,有效载荷中不能包含用户名字段。

如果用户名(User Name)标志被设置为 1,有效载荷中必须包含用户名字段。

2.3.5、密码标志

位置:连接标志的第 6 位。

如果密码(Password)标志被设置为 0,有效载荷中不能包含密码字段。

如果密码(Password)标志被设置为 1,有效载荷中必须包含密码字段。

如果用户名标志被设置为 0,密码标志也必须设置为 0。

2.4 保持连接

表格4.5-保持连接

Bit 7 6 5 4 3 2 1 0
byte9 保持连接 Keep Alive MSB
byte10 保持连接 Keep Alive LSB

保持连接(KEEP ALIVE)是一个以秒为单位的时间间隔,表示为一个 16 位的字,2^16/3600= 18 小时 12 分 15

秒,即设置最大连接时长18.204H,指客户端传输完成一个控制报文的时刻到发送下一个报文的时刻,两者之间允

许空闲的最大时间间隔,如果没有任何其它的控制报文可以发送,客户端必须发送一个 PINGREQ 报文,不管保

持连接的值是多少,客户端任何时候都可以

发送 PINGREQ 报文,客户端收到服务器返回 PINGRESP 报文判断网络和服务端的活动状态。

mqtt 报文_报文怎么解析_https://bianchenghao6.com/blog__第1张

①、如果保持连接的值非零,并且服务端在一点五倍的保持连接时间内没有收到客户端的控制报文,它必须断开客户端的网络连接,认为网络连接已断开。

②、客户端发送了 PINGREQ 报文之后,如果在合理的时间PINGRESP报文,它应该关闭到服务 端的网络连接。

③、保持连接值为0表示客户端不会断开连接,关闭保持连接功能,注意:不管保持连接的值是多少,
只要服务器认为客户端不活跃或者无响应都可以断开连接

2.5、可变报头示例

表格4.6-可变报头示例

描述 7 6 5 4 3 2 1 0
协议名
byte1 长度 MSB (0) 协议长度 0 0 0 0 0 0 0 0
bytE2 长度 LSB (4) 协议长度 0 0 0 0 0 1 0 0
byte3 ‘M’ 0 1 0 0 1 1 0 1
byte4 'Q' 0 1 0 1 0 0 0 1
byte5 'T' 0 1 0 1 0 1 0 0
byte6 'T' 0 1 0 1 0 1 0 0
描述 7 6 5 4 3 2 1 0
协议级别
byte7 Level(4) 0 0 0 0 0 1 0 0
连接标志 Connect Flags
byte 8 User Name Flag (1) 用户名标志 1 1 0 0 1 1 1 0
Password Flag (1) 密码标志
Will Retain (0) Will 保留标志
Will QoS (01) Will 服务质量
Will Flag (1) Will 标志
Clean Session (1) 清理会话
Reserved (0) 保留位
保持连接时间
byte9 保持连接 MSB (0) 0 0 0 0 0 0 0 0
byte10 保持连接 LSB (10) 0 0 0 0 1 0 1 0
3、有效载荷

CONNECT 报文的有效载荷(payload)包含一个或多个以长度为前缀的字段,可变报头中的标志决定是否 包含这些字

段。如果包含的话,必须按这个顺序出现:客户端标识符,遗嘱主题,遗嘱消息,用户名,密 码

表格4.7-有效载荷

Bit 说明 7 6 5 4 3 2 1 0
Client ID
byte1 Client ID Length 0 0 0 0 0 0 0 0
byte2 0 0 0 0 0 1 1 1
一定长度 Client ID 0 0 0 0 0 0 0 0
Will Topic
byte1 Will Topic Length 0 0 0 0 0 0 0 0
byte2 0 0 0 0 0 1 1 1
一定长度 Will Topic 0 0 0 0 0 0 0 0
Will Message
byte1 Will Message Length 0 0 0 0 0 0 0 0
byte2 0 0 0 0 0 1 1 1
一定长度 Will Message 0 0 0 0 0 0 0 0
User Name
byte1 User Name Length 0 0 0 0 0 0 0 0
byte2 0 0 0 0 0 1 1 1
一定长度 User Name 0 0 0 0 0 0 0 0
Password
byte1 Password Length 0 0 0 0 0 0 0 0
byte2 0 0 0 0 0 1 1 1
一定长度 Password 0 0 0 0 0 0 0 0
3.1、 客户端标识符

①、服务端使用客户端标识符 (ClientId) 识别客户端。连接服务端的每个客户端都有唯一的客户端标识符(ClientId)。

②、客户端标识符 (ClientId) 必须存在而且必须是 CONNECT 报文有效载荷的第一个字段

③、服务端可以允许客户端提供一个零字节的客户端标识符,这样服务端会认为是特殊情况自动分配一个且唯一,那样必须将同时将清理会话标志设置为 1

3.2、遗嘱主题

如果可变报头连接标志部分遗嘱标志被设置为 1,则有效载荷的下一个字段是遗嘱主题(Will Topic)。

3.3、 遗嘱消息

如果可变报头连接标志部分遗嘱标志被设置为 1,有效载荷的下一个字段是遗嘱消息。

3.4、 用户名

如果可变报头连接标志部分用户名(User Name)标志被设置为 1,有效载荷的下一个字段就是它。

3.5、 密码

如果可变报头连接标志部分密码(Password)标志被设置为 1,有效载荷的下一个字段就是它。

注意:客户端提供的 ClientId 为零字节且清理会话标志为 0,服务端必须发送返回码为 0x02(表示标识符不合格)的 CONNACK

报文响应客户端的 CONNECT 报文,然后关闭网络连接

也就是说如果你不指定 clientId ,必须清除连接(即将 cleansession 设置为 true)

五、报文分析

首先通过 Wireshark 抓包工具抓取 mqtt 报文,今天总结了 connect 就先对其进行分析吧。

不会使用 Wireshark 软件进行抓包的的可以看看这篇博客,https://www.cnblogs.com/mq0036/p/11187138.html

首先启动你的服务器并运行客户端,填写过滤条件进行抓取,过滤条件为 mqtt 服务器地址和客户端地址

ip.addr == 39.99.222.146 or ip.addr == 192.168.20.72  and mqtt

接下来根据上面讲述的 mqtt connect 报文格式对其进行分析如下
mqtt 报文_报文怎么解析_https://bianchenghao6.com/blog__第2张

mqtt 是应用层协议就是蓝色那部分,将协议以二进制展示
mqtt 报文_报文怎么解析_https://bianchenghao6.com/blog__第3张
报文数据

10 27 00 04 4d 51 54 54 04 c2 00 5a 00 0a 31 35 39 37 32 37 39 

33 33 34 00 07 63 6c 69 65 6e 74 41 00 06 31 32 33 34 35 36

以上面报文数据映射到表格中如下
表格5.1-connect报文

Bit 描述(对应上面的报文数据) 7 6 5 4 3 2 1 0
固定报头
byte1 MQTT报文类型(1) Reserved 保留位
10 0 0 0 1 0 0 0 0
byte2 剩余长度
27 0 0 1 0 0 1 1 1
可变报头
协议名
byte1 长度 MSB (0)         00 0 0 0 0 0 0 0 0
byte2 长度 LSB (4) 协议长度         04 0 0 0 0 0 1 0 0
byte3 ‘M’        4d 0 1 0 0 1 1 0 1
byte4 'Q'        51 0 1 0 1 0 0 0 1
byte5 'T'        54 0 1 0 1 0 1 0 0
byte6 'T'        54 0 1 0 1 0 1 0 0
协议级别
byte7 Level(4)        04 0 0 0 0 0 1 0 0
连接标志 Connect Flags        c2
byte 8 User Name Flag (1) 用户名标志 1 1 0 0 0 0 1 0
Password Flag (1) 密码标志
Will Retain (0) Will 保留标志
Will QoS (01) Will 服务质量
Will Flag (1) Will 标志
Clean Session (1) 清理会话
Reserved (0) 保留位
保持连接时间
byte9 保持连接 MSB (0)        00 0 0 0 0 0 0 0 0
byte10 保持连接 LSB (10)        5a 0 1 0 1 1 0 1 0
有效载荷(出现顺序为客户端标识符,遗嘱主题,遗嘱消息,用户名,密码,下面报文无遗嘱)
客户端标识       其中 Client ID 报文是 char ,int 1 char 49,下列 Client ID 为1597279334
byte11 客户端标识 length        00 0 0 0 0 0 0 0 0
byte12 客户端标识 length        0a 0 0 0 0 1 0 1 0
byte13 客户端标识 Client ID        31 0 0 1 1 0 0 0 1
byte14 客户端标识 Client ID        35 0 0 1 1 0 1 0 1
byte15 客户端标识 Client ID        39 0 0 1 1 1 0 0 1
byte16 客户端标识 Client ID        37 0 0 1 1 0 1 1 1
byte17 客户端标识 Client ID        32 0 0 1 1 0 0 1 0
byte18 客户端标识 Client ID        37 0 0 1 1 0 1 1 1
byte19 客户端标识 Client ID        39 0 0 1 1 1 0 0 1
byte20 客户端标识 Client ID        33 0 0 1 1 0 0 1 1
byte21 客户端标识 Client ID        33 0 0 1 1 0 0 1 1
byte22 客户端标识 Client ID        34 0 0 1 1 0 1 0 0
用户名      User Name Length: 7      User Name: clientA
byte23 User Name Length        00 0 0 0 0 0 0 0 0
byte24 User Name Length        07 0 0 0 0 0 1 1 1
byte25 User Name         63 0 1 1 0 0 0 1 1
byte26 User Name        6c 0 1 1 0 1 1 0 0
byte27 User Name        69 0 1 1 0 1 0 0 1
byte28 User Name        65 0 1 1 0 0 1 0 1
byte29 User Name        6e 0 1 1 0 1 1 1 0
byte30 User Name        74 0 1 1 1 0 1 0 0
byte31 User Name        41 0 1 0 0 0 0 0 1
密码      Password Length: 6      Password: 123456
byte32 Password Length        00 0 0 0 0 0 0 0 0
byte33 Password Length        06 0 0 0 0 0 1 1 0
byte34 Password         31 0 0 1 1 0 0 0 1
byte35 Password        32 0 0 1 1 0 0 1 0
byte36 Password        33 0 0 1 1 0 0 1 1
byte37 Password        34 0 0 1 1 0 1 0 0
byte38 Password        35 0 0 1 1 0 1 0 1
byte39 Password        36 0 0 1 1 0 1 1 0

遗嘱消息如下
mqtt 报文_报文怎么解析_https://bianchenghao6.com/blog__第4张

如上就是 mqtt 的 connect 报文详细映射,有问题可留言探讨,其他报文分析类似,可以自行摸索。

今天的分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。

上一篇

已是最后文章

下一篇

已是最新文章

发表回复