0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

网络协议栈:MQTT的报文格式解析

RTThread物联网操作系统 来源:Rice嵌入式开发技术分享 作者:Rice嵌入式开发技术 2021-05-13 14:06 次阅读

在上一篇文章,直接在本地搭建了服务器和客户端,简单的实践了MQTT的用法。而这一篇来解析MQTT的报文格式。MQTT的报文字段很精简。但是解析起来还是有些复杂的。

解析报文最好的工具是采用wireshark抓包,不过我发现,wireshark的2.xxx的版本无法进行回环抓包(即无法抓取127.0.0.1的数据报文)。通过一番度娘,发现新版本的wireshark用Npcap替换WinPcap,Npcap是基于WinPcap 4.1.3开发的,api兼容WinPcap。

030

MQTT报文

MQTT报文格式

MQTT的报文字段主要包含3部分,如下表:

名称 说明
Fixed header(固定报文头) 所有MQTT报文都包含
Variable header(可变报文头) 只有部分MQTT报文包含
Payload(MQTT数据段) 只有部分MQTT报文包含

MQTT固定报文头[Fixed header]

每个MQTT报文都包含一个固定报文头,固定报文头部格式如下:

bit76543210 +-----+-----+-----+-----+-----+-----+-----+-----+-----+ |Byte1|MQTT控制报文类型|指定控制报文类型的标志| +-----+-----------------------------------------------| |Byte2|剩余长度| +-----+-----------------------------------------------| |...|剩余长度| +-----------------------------------------------------|

MQTT控制报文类型

MQTT的控制报文类型在固定报文头的第1个字节的4 ~ 7bit,共4位无符号值。这些值如下表描述:

类型 报文方向 描述
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 禁止 保留

MQTT控制报文标志

MQTT的控制报文标志在固定报文头的第1个字节的4 ~ 7bit,包含每个MQTT报文类型的特定的标志。

注意:如果接收方收到非法的标志,接受者必须关闭网络连接。标志如下表:

其中:

DUP:控制报文的重复分发标志

QoS:PUBLISH报文的服务质量等级

RETAIN:PUBLISH报文的保留标志

类型 报文标志 Bit3 Bit2 Bit1 Bit0
CONNECT Reserved 0 0 0 0
CONNACK Reserved 0 0 0 0
PUBLISH Used in MQTT 3.1.1 DUP QoS QoS RETAIN
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 0 0 0
PINGRESP Reserved 0 0 0 0
DISCONNECT Reserved 0 0 0 0

MQTT报文剩余长度

剩余长度字段从固定报文头的第2个字节开始,最长可达4个字节,所以剩余长度访问是Byte[2 ~ 5]。

剩余长度表示当前报文剩余部分的字节数,包含可变头部和Payload。

上面的描述,那么怎么确定其长度用几个字节来描述呢?答案:取决于字节的最高位Bit7(默认都是在搞自己在前);如果Bit7为1,那么需要继续计算字节长度,如果Bit7为0,那么不需要继续计算字节长度。

消息长度可以简单理解为128禁止的数据,4位长度最大可以表示:128 * 128 * 128 * 128 Byte = 256MB。

需注意计算规则,低位在前,高位在后,字节最高位Bit7标记是否继续计算消息长度。其消息长度范围如下表:

字节 最小值 最大值
1 0(0x00) 127(0x7F)
2 128(0x80, 0x01) 16383(0xFF, 0X7F)
3 16384(0x80, 0x80, 0x01) 2097151(0xFF, 0xFF, 0x7F)
4 2097152(0x80, 0x80, 0x80, 0x01) 268435455(0xFF, 0xFF, 0xFF, 0x7F)

举例:

第一字节最高位是1,需要继续向后计算,去掉标记位(0xC1%128),得到1000001=41

第二字节最高位是1,需要继续向后计算,去掉标记位(0xC2%128),得到1000010=42

第三字节最高位是0,不需要向后计算,其结果就是0x33=51

因为低位在前,高位在后,即消息长度为:41 + 42 * 128 + 51 * 128 * 128=841001Byte = 821KB

0xC1 = 11000001

0xC2 = 11000010

0x33 = 00110011

消息长度是0x60,其二进制是01100000b,字节最高位Bit7位0,所以不需要往后计算,其十进制是96(即消息长度为96个字节)。

消息长度是0xC1, 0xC2, 0x33。分别二进制为:

MQTT可变报文头[Variable header]

在某些MQTT控制报文包含了一个可变报文头部分,它在固定报文头和payload之间,可变报头的内容根据报文类型的不同而不同,可变报头的报文标识符(Packet Identifier)字段存在与多个类型的报文里。可变报头其实就是MQTT开发中使用的Packet ID,通过Packet ID 进行一些操作确认。包含Packet ID的报文类型如下:

类型 包含可变报文头
PUBLISH √(QoS > 0)
PUBACK
PUBREC
PUBREL
PUBCOMP
SUBSCRIBE
SUBACK
UNSUBSCRIBE
UNSUBACK

Packet ID默认是从1开始并自增,如果一个Packet ID被用完后,这个Packet ID可以被重用。对于PUBLISH(QoS 1)来说,如果发送端接收到PUBACK,那么这个Packet ID就用完了。对于PUBLISH(QoS 2),如果接收方收到PUBCOMP,那么这个Packet ID就用完了。对于SUBSCRIBE和UNSUBSCRIBE,Packet ID使用完成的标记是发送方收到了对应的SUBACK和UNSUBACK。

MQTT数据段[Payload]

MQTT中有些报文类型是包含Payload

如PUBLISH的Payload指消息内容。

如CONNECT的Payload指Client Identifier,Will Topic,Will Message,Username,Password等信息

包含Payload的报文类型如下:

类型 包含Payload
CONNECT
PUBLISH 可选
SUBSCRIBE
SUBACK
UNSUBSCRIBE

通过wireshark分析MQTT报文

因为我们的服务器和客户端是在PC上搭建的,所以需要通过wireshark的回环抓包,来分析报文类型CONNECT和CONNACK。

打开wireshark,选择进行回环抓包

使用MQTT.fx创建一个客户端,点击连接,便可以抓到CONNECT和CONNACK的报文。

红色圈子的报文类型CONNECT的内容:

c4fb05c0-b31f-11eb-bf61-12bb97331649.png

内容: 1025 00044d515454 04 c2 003c 0008636c69656e743031 000561646d696e 00083132333435363738

报文类型CONNECT内容分析:

0x10:高四位0001,代表报文类型:CONNECT。

0x25:二进制-0010 0101,Bit7为0,所以剩余长度只有一个字节长,即0x25十进制:37个字节

0x00 0x04 0x4d 0x51 0x54 0x54:其中-0x00,0x04表示协议长度;0x4d 0x51 0x54 0x54对应 "M", "Q", "T", "T"。

0x04:代表MQTT版本号:v3.1.1

0xc2: 次字节含义如下表,该字节描述紧跟数据有 User Name、Password,没有遗嘱设置,选择了清理会话方式与服务器连接。

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


00 3c:对应十进制为60,即保持连接(Keep Alive)60秒,以秒为单位,它是指在客户端传输完成一个控制报文的时刻到发送下一个报文的时刻,两者之间允许空闲的最大时间间隔。客户端负责保证控制报文发送的时间间隔不超过保持连接的值。如果没有任何其它的控制报文可以发送,客户端 必须发送一个PINGREQ 报文。客户端随时可以发送ping指令,服务器如果发现在KeepAalive时间内没有收到客户端的消息,会自动断开与客户端建立的连接。

00 08 63 6c 69 65 6e 74 30 31:其中-0x00, 0x08表示clientID的长度8个字节;0x63,0x6c,0x69,0x65,0x6e,0x74,0x30,0x31:代表client01。即是我们在MQTT.fx创建客户端的时候设置clientID。

00 05 61 64 6d 69 6e:其中-0x00,0x05表示User Name的的长度5个字节;0x61,0x64,0x6d,0x69,0x6e:代表User Name为admin,即是我们在MQTT.fx创建客户端的时候设置User Name。

00 08 31 32 33 34 35 36 37 38:其中-0x00,0x08表示User Name的的长度8个字节;0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38:代表Password为12345678,即是我们在MQTT.fx创建客户端的时候设置Password。

红色圈子的报文类型CONNACK的内容:

c5174456-b31f-11eb-bf61-12bb97331649.png

内容: 20 02 00 00

报文类型CONACK内容分析:

20:高四位0010,代表报文类型:CONNACK。

02:二进制-0000 0010,Bit为0,所以剩余长度只有一个字节长,即0x02十进制:2个字节。

00:可变头部的第一个字节的第0位连接确认。

c5331d3e-b31f-11eb-bf61-12bb97331649.png

00:可变头部的第二个字节。

返回码响应 描述
0 0x00连接已接受 连接已被服务器接受
1 0x01连接已拒绝,不支持的协议版本 服务器不支持客户端请求的协议版本
2 0x02连接已拒绝,不合格的客户端ID 客户端ID是正确的UTF-8码,但服务器不允许使用
3 0x03连接已拒绝,服务端不可用 网络连接已建立,但MQTT服务不可用
4 0x04连接已拒绝,无效的用户名或密码 用户名或密码的数据格式无效
5 0x05连接已拒绝,未授权 客户端未被授权连接到此服务器
6-255 Reserved 保留

原文标题:教你动手写网络协议栈-MQTT报文解析6-解析

文章出处:【微信公众号:RTThread物联网操作系统】欢迎添加关注!文章转载请注明出处。

责任编辑:haq
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 网络
    +关注

    关注

    14

    文章

    7251

    浏览量

    87440
  • 报文数据
    +关注

    关注

    0

    文章

    3

    浏览量

    7557

原文标题:教你动手写网络协议栈-MQTT报文解析6-解析

文章出处:【微信号:RTThread,微信公众号:RTThread物联网操作系统】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    modbus报文解析,modbus报文格式详解

    支持点对点和多点通信,可以实现控制器之间的通信。 Modbus报文是Modbus协议中的基本通信单位。Modbus报文包含一个头部和数据部分。头部包含了从站地址、功能码和数据长度等信息,数据部分包含了请求或响应数据。 1. 地址
    的头像 发表于 04-16 15:16 122次阅读

    CAN报文为什么会发送失败?

    怎么样的。表1是一帧正常标准数据帧的报文组成。表1标准数据帧报文格式组成图1标准数据帧格式CAN总线是一种基于广播的通讯方式,为了保证总线上的每一个正常节点都能正
    的头像 发表于 04-12 08:25 185次阅读
    CAN<b class='flag-5'>报文</b>为什么会发送失败?

    CAN的报文格式和发送总流程

    在标准格式中,报文的起始位称为帧起始(SOF),然后是由11位标识符和远程发送请求位(RTR)组成的仲裁场。RTR位标明是数据帧还是请求帧,在请求帧中没有数据字节。
    发表于 04-11 10:07 314次阅读
    CAN的<b class='flag-5'>报文格式</b>和发送总流程

    modbus报文解析,modbus报文格式详解

    支持点对点和多点通信,可以实现控制器之间的通信。 Modbus报文是Modbus协议中的基本通信单位。Modbus报文包含一个头部和数据部分。头部包含了从站地址、功能码和数据长度等信息,数据部分包含了请求或响应数据。   1.
    的头像 发表于 01-09 16:45 3125次阅读

    IPv4报文格式各字段的含义

    Version版本 4Bit :ip报文中,用来表示该协议采用的是那一个版本的ip,相同版本的ip才能进行通信。一般此处的值为4,表示ipv4。
    的头像 发表于 12-13 09:43 811次阅读
    IPv4<b class='flag-5'>报文格式</b>各字段的含义

    关于TCP协议总结的硬核干货

    本文给出TCP报文格式的详细说明,介绍网络数据包传递中如何进行地址解析、建立TCP连接的三次握手过程以及断开TCP连接的四次挥手过程。
    发表于 11-17 09:26 235次阅读
    关于TCP<b class='flag-5'>协议</b>总结的硬核干货

    TCP协议详细解析

    TCP是TCP/IP协议族中一个最核心的协议,它向下使用网络层IP协议,向上为应用层HTTP、FTP、SMTP、POP3、SSH、Telnet等协议
    的头像 发表于 11-03 09:14 1695次阅读
    TCP<b class='flag-5'>协议</b>详细<b class='flag-5'>解析</b>

    MQTT协议采集网关可自定义格式

    语言如Java或C++,以及Modbus RTU协议库和MQTT协议库。首先,我们需要通过串口或网络接口接收Modbus RTU协议的数据;
    发表于 10-09 19:33

    Path延时测量相关报文格式介绍

    Pdelay_Req报文格式定义 如下图15所示为IEEE802.1AS定义的报文格式定义: 图15 Pdelay_Req报文格式定义 上图中header与SYNCMessage头信息定义
    的头像 发表于 07-24 10:45 686次阅读
    Path延时测量相关<b class='flag-5'>报文格式</b>介绍

    C语言代码封装MQTT协议报文,了解MQTT协议通信过程

    MQTT是一种轻量级的通信协议,适用于物联网(IoT)和低带宽网络环境。它基于一种“发布/订阅”模式,其中设备发送数据(也称为 “发布”)到经纪人(称为MQTT代理),这些数据被存储,
    的头像 发表于 05-17 09:24 2407次阅读

    【教程】CAN报文固定协议转发

    在CAN总线通信的应用领域中,很多客户需要将CANID放在CAN报文中,这样更方便接入不同的设备,有利于用户通过模块更方便的组建自己的网络,使用自定的应用协议。但是要实现这样的应用,用户往往需要
    的头像 发表于 05-15 10:30 476次阅读
    【教程】CAN<b class='flag-5'>报文</b>固定<b class='flag-5'>协议</b>转发

    CAN报文固定协议转发教程

    在CAN总线通信的应用领域中,很多客户需要将CANID 放在CAN报文中,这样更方便接入不同的设备,有利于用户通过模块更方便的组建自己的网络,使用自定的应用协议。但是要实现这样的应用,用户往往需要
    的头像 发表于 05-12 10:40 592次阅读
    CAN<b class='flag-5'>报文</b>固定<b class='flag-5'>协议</b>转发教程

    WPF上位机通信组件与Modbus协议

    ) - 以太网(TCP点对点):ModbusTCP、ModbusUDP 报文格式一样 RTUover TCP 以TCP的方式发送RTU的报文 - 其他连接方式:设备方支持ModbusRTU 可以:关心1、能不能把byte[]发送过去,2、接收到的
    发表于 05-10 10:32 7次下载
    WPF上位机通信组件与Modbus<b class='flag-5'>协议</b>

    HTTP协议报文格式

    请求行以方法字段开始,后面分别是URL字段和HTTP协议版本字段,并以CRLF结尾。SP是分隔符。除了在最后的CRLF序列中CF和LF是必需的之外,其他都可以不要。有关通用信息头,请求头和实体头方面的具体内容可以参照相关文件。
    发表于 05-06 15:56 2960次阅读

    UDP协议报文格式

    UDP用来支持那些需要在计算机之间传输数据的网络应用。包括网络视频会议系统在内的众多的客户/服务器模式的网络应用都需要使用UDP协议
    发表于 05-06 15:26 2688次阅读
    UDP<b class='flag-5'>协议</b>的<b class='flag-5'>报文格式</b>