我是靠谱客的博主 美满哈密瓜,最近开发中收集的这篇文章主要介绍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-固定报头格式

Bit76543210
byte1MQTT控制报文类型用于指定控制报文类型的控制位
byte2 剩余长度

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

名字报文流动方向描述
Reserved0禁止保留
CONNECT1客户端到服务端客户端请求连接服务端
CONNACK2服务端到客户端连接报文确认
PUBLISH3两个方向都允许发布消息
PUBACK4两个方向都允许QoS 1 消息发布收到确认
PUBREC5两个方向都允许发布收到(保证交付第一步)
PUBREL6两个方向都允许发布释放(保证交付第二步 )
PUBCOMP7两个方向都允许QoS 2 消息发布完成(保证交互第三步)
SUBSCRIBE8客户端到服务端客户端订阅请求
SUBACK9服务端到客户端订阅请求报文确认
UNSUBSCRIBE10客户端到服务端客户端取消订阅请求
UNSUBACK11服务端到客户端取消订阅报文确认
PINGREQ12客户端到服务端心跳请求
PINGRESP13服务端到客户端心跳响应
DISCONNECT14客户端到服务端客户端断开连接
Reserved15禁止保留

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

控制报文固定报头标志Bit3Bit2Bit1Bit0
CONNECTReserved0000
CONNACKReserved0000
PUBLISHUsed in MQTT 3.1.1DUP1QoS2QoS2RETAIN3
PUBACKReserved0000
PUBRECReserved0000
PUBRELReserved0010
PUBCOMPReserved0000
SUBSCRIBEReserved0010
SUBACKReserved0000
UNSUBSCRIBEReserved0010
UNSUBACKReserved0000
PINGREQReserved0 v000
PINGRESPReserved0000
DISCONNECTReserved0000

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-固定报头

Bit76543210
byte1MQTT报文类型(1)Reserved 保留位
00010000
byte2 剩余长度
根据 表格2.2-mqtt 控制报文类型 和 表格 2.3 -标志位 查询数据
2、 可变报头

某些 MQTT 控制报文包含一个可变报头部分。它在固定报头和负载之间。可变报头的内容根据报文类型的不同而不

同。可变报头的报文标识符(Packet Identifier)字段存在于在多个类型的报文里。如:**CONNECT 报文的可变报头

**按下列次序包含四个字段:协议名(Protocol Name),协议级别(Protocol Level),连接标志(Connect

Flags)和保持连接(Keep Alive)。不同控制报文可变头部不同

2.1、协议名

表格4.2-协议名

说明76543210
协议名
byte1长度 MSB (0) 协议长度00000000
bytE2长度 LSB (4) 协议长度00000100
byte3‘M’01001101
byte4'Q'01010001
byte5'T'01010100
byte6'T'01010100
2.2、协议级别

表格4.3-协议级别

说明76543210
协议级别
byte7Level(4)00000100
Level(4) 为mqtt 3.1.1 版协议,协议级别字段的值是 4(0x04)。
2.3、连接标志

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

表格4.4-连接标志位

Bit76543210
User Name FlagPassword FlagWill RetainWill QoSWill FlagClean SessionReserved
Level(4)xxxxxxx0
服务端必须验证 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-保持连接

Bit76543210
byte9保持连接 Keep Alive MSB
byte10保持连接 Keep Alive LSB

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

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

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

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

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

在这里插入图片描述

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

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

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

2.5、可变报头示例

表格4.6-可变报头示例

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

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

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

表格4.7-有效载荷

Bit说明76543210
Client ID
byte1Client ID Length00000000
byte200000111
一定长度Client ID 00000000
Will Topic
byte1Will Topic Length00000000
byte200000111
一定长度Will Topic00000000
Will Message
byte1Will Message Length00000000
byte200000111
一定长度Will Message 00000000
User Name
byte1User Name Length00000000
byte200000111
一定长度User Name 00000000
Password
byte1Password Length00000000
byte200000111
一定长度Password 00000000
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

   
   
  • 1

接下来根据上面讲述的 mqtt connect 报文格式对其进行分析如下
在这里插入图片描述

mqtt 是应用层协议就是蓝色那部分,将协议以二进制展示
在这里插入图片描述
报文数据

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

  • 1
  • 2
  • 3

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

Bit描述(对应上面的报文数据)76543210
固定报头
byte1MQTT报文类型(1)Reserved 保留位
1000010000
byte2 剩余长度
2700100111
可变报头
协议名
byte1长度 MSB (0)         00 00000000
byte2长度 LSB (4) 协议长度         0400000100
byte3‘M’        4d01001101
byte4'Q'        5101010001
byte5'T'        5401010100
byte6'T'        5401010100
协议级别
byte7Level(4)        0400000100
连接标志 Connect Flags        c2
byte 8User Name Flag (1) 用户名标志11000010
Password Flag (1) 密码标志
Will Retain (0) Will 保留标志
Will QoS (01) Will 服务质量
Will Flag (1) Will 标志
Clean Session (1) 清理会话
Reserved (0) 保留位
保持连接时间
byte9保持连接 MSB (0)        0000000000
byte10保持连接 LSB (10)        5a01011010
有效载荷(出现顺序为客户端标识符,遗嘱主题,遗嘱消息,用户名,密码,下面报文无遗嘱)
客户端标识       其中 Client ID 报文是 char ,int 1 char 49,下列 Client ID 为1597279334
byte11客户端标识 length        00 00000000
byte12 客户端标识 length        0a00001010
byte13客户端标识 Client ID        3100110001
byte14客户端标识 Client ID        3500110101
byte15客户端标识 Client ID        3900111001
byte16客户端标识 Client ID        3700110111
byte17客户端标识 Client ID        3200110010
byte18客户端标识 Client ID        3700110111
byte19客户端标识 Client ID        3900111001
byte20客户端标识 Client ID        3300110011
byte21客户端标识 Client ID        3300110011
byte22客户端标识 Client ID        3400110100
用户名      User Name Length: 7      User Name: clientA
byte23User Name Length        0000000000
byte24User Name Length        0700000111
byte25User Name         6301100011
byte26User Name        6c01101100
byte27User Name        6901101001
byte28User Name        6501100101
byte29User Name        6e01101110
byte30User Name        7401110100
byte31User Name        4101000001
密码      Password Length: 6      Password: 123456
byte32Password Length        0000000000
byte33Password Length        0600000110
byte34Password         3100110001
byte35Password        3200110010
byte36Password        3300110011
byte37Password        3400110100
byte38Password        3500110101
byte39Password        3600110110

遗嘱消息如下
在这里插入图片描述

如上就是 mqtt 的 connect 报文详细映射。本来想自己写的,但是这位大佬写的很全面了,于是转载了大佬的博客

这是原文连接:https://blog.csdn.net/qq_41538097/article/details/107963579

最后

以上就是美满哈密瓜为你收集整理的MQTT报文解析的全部内容,希望文章能够帮你解决MQTT报文解析所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(41)

评论列表共有 0 条评论

立即
投稿
返回
顶部