文章目录

  • 1、背景说明
  • 2、mqtt报文解析
  • 3、剩余长度计算
  • 4、构建connect报文
  • 5、CONNACK报文示例
  • 6、心跳PING报文
  • 7、心跳回应PINGRESP报文
  • 8、断开连接DISCONNECT报文
  • 9、订阅请求SUBSCRIBE
  • 10、订阅请求确认SUBACK
  • 11、取消订阅UNSUBSCRIBE
  • 12、取消订阅确认UNSUBACK
  • 13、发布消息PUBLISH(服务质量等级为0)
  • 14、发布确认PUBACK
  • 15、其他报文
  • 16、本地测试方法

1、背景说明

本文还是需要参考mqtt的中文协议文档,所有的变种都是基于这个的。

本文有看不懂的地方需要参考一点我之前的文章:

STM32使用esp01s上云,MQTT.fx调试述
阿里云使用记录

相信看完一定对mqtt协议有更深入的了解!

2、mqtt报文解析

之前的文章已经提到过一些mqtt的格式,这里不再赘述,需要的可以直接翻看之前的文章了解查看,目前mqtt总的报文如下:

下面分别说明这些报文:

connect是一号报文,需要第一个发送,包括一些鉴权信息(用户名,密码等),方向是从客户端到服务器,二号报文是服务器回复客户端的,回复客户端连接正确与否,方向是从服务器到客户端。

之后关注一下ping相关的报文,PING报文,是用于保活的,方向从客户端到服务器,定期发送保活,同样服务器也要定期回复客户端,就是PINGRSP报文,这样就能建立一个长期的连接了。最后的一个是断开连接,断开连接由客户端发起,服务器无需回应报文。

下面关注一下订阅相关的报文,分为订阅和取消订阅,订阅和取消订阅都是由客户端发起的,同时服务器需要有相对应的回应。

下面是正式的数据通信部分的报文了,数据通信这里就是发布消息的报文,这个过程是双向的,两边都可以实现这个报文,可以看下面的箭头描述,同时需要注意目前绝大多是的mqtt服务器都不支持质量等级为QoS2的通信,所以就都不用关下面的几种消息发布了。

以上就是所有关于mqtt的报文的拆分和解析了,下面来具体看这些报文是如何实现的。

3、剩余长度计算

基本上每种报文都需要可变长度,所以每次发消息就都需要计算可变长度(12,13,14号报文没有可变报头和负载,可变长度直接就是00,如下图所示)。

剩余长度的的计算值可以表示为可变报头+负载,最少占用一个字节,最多占用4个字节,这个在前面的文章里面也提到过了,这里在说一点细节相关的东西吧:

看上面的规则,这里比如剩余长度是32,那就是:0x20

下面假如一个长度超过127就是200吧,需要第二个字节来帮忙表示,那就是200-128=72,这里是0x48,

但是还需要表示进位,就是第一个位来表示进位,那就是:0xc8

所以这个里面最终的计算结果为:0xc8 0x01

下面再来看一个更大的数字,就以20000为例子来查看一下吧,两个字节最大表示16383,所以需要三个字节才能表示的清楚这个数字:20000 - 156*128=32所以最下面的一个是32,32再用进位来表示一下:0xA0

之后就是156了,很明显,156也需要进位,那就是156-128=28,进位表示为:0x9c

所以这样最终的结果就是 0xa0 0x9c 0x01,相信通过这个例子能更加看清这个剩余长度的计算方法了。

4、构建connect报文

需要注意就是:在一个网络连接上,客户端只能发送一次 CONNECT 报文。服务端必须将客户端发送的第二个 CONNECT报文当作协议违规处理并断开客户端的连接,所以这一次的连接建立还是很重要的。

首先是固定报头:0x10(直接一眼看出来就是),下面是剩余长度,剩余长度是要等于可变报头的长度加上有效载荷才行,所以这里暂时不知道剩余长度,等确定了内容就知道了。

这里connect报文的可变报头总共是10个字节,分别为:协议名(Protocol Name),协议级别(Protocol
Level),连接标志(Connect Flags)和保持连接(Keep Alive)。

协议名如下所示,直接一眼看出:00 04 4D 51 54 54


下面是协议级别:04

连接标识,这里除了用户名和密码(可以以游客的身份登陆),其他的都可以不要,最后加上一个清理会话,最终的结果就是C2

保持连接:这里是心跳保活的时间,这里选一个100秒吧,就是64

这样就确定了可变报头的内容:00 04 4D 51 54 54 04 C2 00 64,一个是个字节的长度。

之后是有效载荷的部分了,有效载荷,这里根据平台有不同的选择,这里用的阿里云的平台,相关说明如下所示,注意看这个路径位置:

这里我们最终拼接的内容如下所示:

当然也可以偷懒,直接去官方产品页面查看,这里我的mqtt连接参数如下所示,这里的连接参数为mqtt的连接参数

复制下来如下所示:

但是发现好像连接端不是需要这个部分的内容,根据官方文档资料,说明的connect的参数应该是这样的:

这个内容可以在MQTT的连接参数中查看到数据,最终形成的连接内容应该是如下所示:

gukv3BQLi1G.camera1|securemode=2,signmethod=hmacsha256,timestamp=1663601981496|
camera1&gukv3BQLi1G
2b4af23ae4840f34aad897e743b776d847e2aa6d966bef19e08ea2e2e2b74384

这里也是根据官方协议来看的,官方协议在CONNECT的报文的可变内容中描述如下:

同时也对每个部分的内容做了要求,简单来说就是长度加上内容

下面来具体的对上述部分进行封装

首先是mqttClientId,转成16进制再发送:00 4f(长度79)

之后是:mqttUsername,转成16进制再发送:00 13(长度19)

最后是:mqttPassword,转成16进制再发送:00 40(长度64)

所以最后的内容断数据为:(每条的长度+每条的内容)

00 4F 67 75 6B 76 33 42 51 4C 69 31 47 2E 63 61 6D 65 72 61 31 7C 73 65 63 75 72 65 6D 6F 64 65 3D 32 2C 73 69 67 6E 6D 65 74 68 6F 64 3D 68 6D 61 63 73 68 61 32 35 36 2C 74 69 6D 65 73 74 61 6D 70 3D 31 36 36 33 36 30 31 39 38 31 34 39 36 7C00 13 63 61 6D 65 72 61 31 26 67 75 6B 76 33 42 51 4C 69 31 4700 40 32 62 34 61 66 32 33 61 65 34 38 34 30 66 33 34 61 61 64 38 39 37 65 37 34 33 62 37 37 36 64 38 34 37 65 32 61 61 36 64 39 36 36 62 65 66 31 39 65 30 38 65 61 32 65 32 65 32 62 37 34 33 38 34

总的可变长度就是10+79+19+64+6=178,表示为 0xB2 0x01

因此最终发送的内容为:

10 B2 01 00 04 4D 51 54 54 04 C2 00 64 00 4F 67 75 6B 76 33 42 51 4C 69 31 47 2E 63 61 6D 65 72 61 31 7C 73 65 63 75 72 65 6D 6F 64 65 3D 32 2C 73 69 67 6E 6D 65 74 68 6F 64 3D 68 6D 61 63 73 68 61 32 35 36 2C 74 69 6D 65 73 74 61 6D 70 3D 31 36 36 33 36 30 31 39 38 31 34 39 36 7C 00 13 63 61 6D 65 72 61 31 26 67 75 6B 76 33 42 51 4C 69 31 47 00 40 32 62 34 61 66 32 33 61 65 34 38 34 30 66 33 34 61 61 64 38 39 37 65 37 34 33 62 37 37 36 64 38 34 37 65 32 61 61 36 64 39 36 36 62 65 66 31 39 65 30 38 65 61 32 65 32 65 32 62 37 34 33 38 34

数据发送如下所示:

可以看到返回的消息如下所示:

5、CONNACK报文示例

可以看到上面发送完(这里一定是建立在发送了正确的CONNECK报文的基础上)CONNECK报文之后,服务器返回了 20 02 00 00的四个数据,下面来查看下这四个数据表示的含义:

首先是CONNACK报文的连接确认:20 02(这是固定报头)

可变报头的描述如下所示,可以看到第一个字节也是00

第二个是连接返回码,关于连接返回码的表示如下所示:

从上表中可以看出,连接返回码为00 正是表示服务器接受连接的意思,所以这个就很正常了,表示连接正确建立。

同时去阿里云的物联网平台也可以看到设备连接上了:

6、心跳PING报文

这里就一个报头,直接从表中读数据就行,应该就是C0 00

发送可以看到数据的返回:

同时刚才的过程也可以用wireshark工具来抓包看看是什么数据:

上面的地方设置规则为mqtt即可,相关的报文详解如下所示:

7、心跳回应PINGRESP报文

服务端发送 PINGRESP 报文响应客户端的 PINGREQ 报文。 表示服务端还活着,相关描述如下所示:(这个也是只有固定报头一项参数可以用

根据上面图表的描述,可以知道,服务器正确返回的参数应该是:D0 00

8、断开连接DISCONNECT报文

DISCONNECT 报文是客户端发给服务端的最后一个控制报文。表示客户端正常断开连接。下面是相关的描述参数,这个同样是只有一项参数固定报头。

根据上面图表的描述,可以知道,服务器正确返回的参数应该是:E0 00

发送完成之后就可以看到服务器主动断开了连接,说明这个报文还是很有用的!

9、订阅请求SUBSCRIBE

查文档可以看到固定报头是 82 xx(剩余长度暂不清楚)

下面是可变报头,这里的可变报头是指报文标识符的部分:

上面是00 10为报文标识符等于10的可变报头,那我们可以自己选的,就是说这个标识符只是用来区别不同报文的,那这里选一个 00 01

这里我们去阿里云找一个主题来订阅下看看


替换设备名称后结果如下所示:

/sys/gukv3BQLi1G/camera1/thing/service/property/set
转成16进制 下面长度是53个字节2F 73 79 73 2F 67 75 6B 76 33 42 51 4C 69 31 47 2F 63 61 6D 65 72 61 31 2F 74 68 69 6E 67 2F 73 65 72 76 69 63 65 2F 70 72 6F 70 65 72 74 79 2F 73 65 74

所以根据这个长度拼接一下:

00 33 2F 73 79 73 2F 67 75 6B 76 33 42 51 4C 69 31 47 2F 63 61 6D 65 72 61 31 2F 74 68 69 6E 67 2F 73 65 72 76 69 63 65 2F 70 72 6F 70 65 72 74 79 2F 73 65 74

但是这还不够,订阅还需要一个质量等级,但是这个质量等级这里不需要算到长度里面

阿里云这里默认都是0,所以直接用0就行了:

这样的话现在的内容就是这样了:

00 33 2F 73 79 73 2F 67 75 6B 76 33 42 51 4C 69 31 47 2F 63 61 6D 65 72 61 31 2F 74 68 69 6E 67 2F 73 65 72 76 69 63 65 2F 70 72 6F 70 65 72 74 79 2F 73 65 74 00

再次对总长度进行拼接(之前不清楚的剩余长度现在就可以计算出来了):

82 38
00 01
00 33 2F 73 79 73 2F 67 75 6B 76 33 42 51 4C 69 31 47 2F 63 61 6D 65 72 61 31 2F 74 68 69 6E 67 2F 73 65 72 76 69 63 65 2F 70 72 6F 70 65 72 74 79 2F 73 65 74 00

最上面一行是报文标识符和剩余长度,第二行是报文标识符,第三行是订阅的主题长度和主题

发送,可以看到阿里云回复如下所示:

同时可以在阿里云的后台看到消息如下所示:

10、订阅请求确认SUBACK

上面已经成功订阅了主题,并收到了服务器的消息回复,这里我们直接分析一下服务器回复的消息就行了:

回复了 90 03 00 01 01

查文档可以知道 90 03为固定报头还有剩余长度

00 01位可变报头,这里也可以直接认为是报文标识符,我们之前设置的是 00 01,那他回复的就是 00 01

最后一个01 是最大支持的服务质量等级 01表示最大为服务等级1

11、取消订阅UNSUBSCRIBE

查文档可以看到取消订阅的报头为:A2 XX(剩余长度暂不清楚)

之后就是标识符还有有效载荷的部分了,类似这种取消的都比较简单,这里标识符我们换一个 00 02(上面用过00 01了)

另外需要注意取消订阅不需要服务质量等级,剩下的直接抄:(上面订阅了什么这里就取消什么,因此内容字段直接抄

下面来发送进行一下测试:

阿里云后台的信息如下所示:

上述说明成功实现了订阅和取消订阅

12、取消订阅确认UNSUBACK

上面我们已经拿到了取消订阅的返回,其实就是UNSUBACK的报文信息,下面来详细分析一下这个部分的报文:
B0 02 00 02

其实还是看文档,因为这个服务器一定是按照文档来写的:

从图中可以知道 B0 02是固定报头和剩余长度,00 02是我们刚才取消订阅的报文标识符

OK,解析完成!

13、发布消息PUBLISH(服务质量等级为0)

这里还是先看一下头:

这里其他部分都不要,服务质量等级选0,因此就是 30 xx(剩余长度不清楚),下面可变报头的部分,可以看到,这里可变报头是需要包含主题的

这里我们用一个属性上报来做实验:

因此就是:(前面是长度,后面是topic)

00 32 2F 73 79 73 2F 67 75 6B 76 33 42 51 4C 69 31 47 2F 63 61 6D 65 72 61 31 2F 74 68 69 6E 67 2F 65 76 65 6E 74 2F 70 72 6F 70 65 72 74 79 2F 70 6F 73 74

下面是报文标识符,这里因为我们用Qos = 0,所以就没有报文标识符

下面是发送内容:(内容本来是可以随便发的,但是阿里云有要求,不能随便发)

这里我们要用之前的物模型:(这里我用的我之前测试的一个物模型吧)

在阿里云平台导出物模型就是这样的:

这里我们要设置他的属性就需要:(这里内容为什么是这个可以看我之前的文章,其实就是用set属性发一下一个参数看他发送的是什么就可以反推内容了

{"method":"thing.service.property.set","id":"1993907181","params":{"test111":0},"version":"1.0.0"}

因此我们来构造一下我们的报文:(发布的内容如下,下面我转成了16进制的内容

内容:

发布消息:
/sys/gukv3BQLi1G/camera1/thing/event/property/post 50
{"method":"thing.service.property.set","id":"1993907181","params":{"test111":0},"version":"1.0.0"} 98
30 96 01
00 32 2F 73 79 73 2F 67 75 6B 76 33 42 51 4C 69 31 47 2F 63 61 6D 65 72 61 31 2F 74 68 69 6E 67 2F 65 76 65 6E 74 2F 70 72 6F 70 65 72 74 79 2F 70 6F 73 74
7B 22 6D 65 74 68 6F 64 22 3A 22 74 68 69 6E 67 2E 73 65 72 76 69 63 65 2E 70 72 6F 70 65 72 74 79 2E 73 65 74 22 2C 22 69 64 22 3A 22 31 39 39 33 39 30 37 31 38 31 22 2C 22 70 61 72 61 6D 73 22 3A 7B 22 74 65 73 74 31 31 31 22 3A 30 7D 2C 22 76 65 72 73 69 6F 6E 22 3A 22 31 2E 30 2E 30 22 7D 

下面用我们在之前构建好的客户端给他发送出去,然后看一下回来接收的内容:

这里为了证实我们成功发布了消息,可以在阿里云的日志这里看到我们发布的消息:

同时在物模型这里可以看到我们的物模型发生了变化:

14、发布确认PUBACK

这里因为我们上面采用的是QoS0级别的消息发送,所以应该是没有内容回复的,因为这个级别不需要知道另一方有没有收到消息,如果不是QoS0级别的才要看有没有确认:

同样的也可以看到这个的发布确认发布头如下所示:为 40 02

那他就是固定长度为为40 然后长度为02,然后02是报文标识符:(报文标识符自然要和订阅的报文是相关的!

这里没有有效载荷。

15、其他报文

其他报文都是和Qos2等级相关的,因此这里就不讨论了!

16、本地测试方法

本地可以自己搭建服务器进行测试,这里我推荐mosquitto,也有人推荐使用emqx,但是我觉得使用emqx有点蛮烦,如果是做开发可能更方便一点吧,这里直接介绍使用mosquitto的方案吧!

下载链接如下所示:

https://mosquitto.org/download/


可以根据需求下载,这里我用的是win版本的,比较方便,下面是一些建议设置:

之后设置我们服务器的启动为手动:


之后找到下载安装的路径,点击启动即可

之后就会出现这样一个黑框,不要关闭它,我们的服务器就一直都在:

新建一个其他的窗口来订阅和发布主题:

常见的命令如下:

运行服务器:

mosquitto -v

订阅主题:

mosquitto_sub  -v -t mytopic

发布主题:

mosquitto_pub  -t mytopic -m "xxxxxxxx"

当然他的功能远不止这么点,这些只是示例。

mqtt报文逐条解析相关推荐

  1. MQTT协议-报文分析及网络客户端报文测试(MQTT报文连接阿里云上传数据+订阅数据)

    文章目录 一.本文章所涉及到的内容 二.感性认识MQTT协议 三.准备信息 (一)工具获取 (二)获取信息 1.获取三元组信息 2.获取发布topic和订阅topic 3.客户端ID,用户名,哈希加密 ...

  2. MQTT协议图解,一文看懂MQTT协议数据包(真实报文数据解析解释)

    文章目录 一.MQTT协议 二.协议详解 2.1 协议结构 2.1.1 固定报头 2.1.2 可变报头 2.1.3 有效载荷 三.具体协议报文详解 3.1 连接服务器报文详解 3.2 发布消息报文详解 ...

  3. mqtt报文解析—超详细

    文章目录 一.报文结构 二.固定报头 三.剩余长度 四.mqtt控制报文 Ⅰ.CONNECT 1.固定报头 2. 可变报头 2.1.协议名 2.2.协议级别 2.3.连接标志 2.4 保持连接 2.5 ...

  4. 【Java 虚拟机原理】栈帧 | 局部变量表 | 操作数栈 | 方法出口 | JVM 指令逐条解析

    文章目录 前言 一.JVM 指令逐条解析 1.Java 代码 2.Java 虚拟机指令 3.分析 JVM 指令 4.局部变量表 与 操作数栈 二.方法出口 前言 " 栈帧 " 中存 ...

  5. 常用报文的解析与相互转换

    分享一下我老师大神的人工智能教程.零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow 常用报文的解析与相 ...

  6. c语言解析字符串报文,传递字符串数组报文和解析

    1 .项目中,难免遇到两个系统平台数据的交互,此时就需要通过接口来完成了: 2.WebService 基于 HTTP 通信,它跨平台,使得易购平台能无缝衔接,将应用程序的逻辑和数据暴露,使得其他应用系 ...

  7. Java开发笔记XML报文的解析

    Java开发笔记XML报文的解析 前言 正文 代码示例 结语 前言 项目任务里需要解析xml报文. 于是开始着手学习相关知识,在查看了多篇博文后找到了一篇不错的,讲的很实用. 转载来源:Java开发笔 ...

  8. can总线用java怎么解析_CAN报文DBC解析的编程方法说明

    主要内容1. 概述2. 我们要做一件什么事情在软件框架中的位置 DBC介绍3. 我们怎么去做这件事情数据存储 输入输出1概述前面介绍过PEAK的所有CAN卡都有提供如下图所示这些二次开发包,非常适合于 ...

  9. TCP 的那些事 | TCP报文格式解析

    TCP(Transmission Control Protocol 传输控制协议)提供一种面向连接的.可靠的字节流服务.面向连接意味着两个使用TCP的应用(通常是一个客户和一个服务器)在彼此交换数据之 ...

最新文章

  1. java 发送邮件 菜鸟_Java发送邮件的方法
  2. java http连接_Java中通过方法创建一个http连接并请求(服务器间进行通信)
  3. Tableau必知必会之图表显示部分标签的小妙招
  4. 字符串最长公共子序列python_求解两个字符串的最长公共子序列
  5. Broker 的 Heap Size 如何设置?
  6. 怎样在php中制作电子相册,电子相册制作 如何制作电子相册带音乐和文字
  7. 以4%参数量比肩GPT-3!Deepmind 发布检索型 LM,或将成为 LM 发展新趋势!?
  8. 纯手工获取的WINDOWS 7 32位 SP1后续补丁集ver201509的官方下载地址
  9. 应届生年薪 40w 在杭州可以过上什么样的生活?
  10. 网络宽带和实际下载速度单位换算详解:
  11. 一文读懂 Kafka 事务机制
  12. 玩游戏掉帧严重?看过来!
  13. 计算机为什么要学16进制,为什么人们通常用十六进制而不是二进制写计算机
  14. M1芯片真正原生版本photoshop 2021安装 PS2021 Mac版 附详细教程!再无需rosetta转译!!
  15. 北航计算机学院硕士培养方案,北航硕士研究生培养方案
  16. 通信电子电路(二十) 第一章复习+习题讲解
  17. Cartopy绘制地图
  18. 洛谷 P4726 【模板】多项式指数函数
  19. 科技爱好者周刊(第 183 期):腾讯的员工退休福利
  20. springboot蓝天幼儿园管理系统、

热门文章

  1. XYNUOJ1561-广告印刷
  2. c语言里的负数用16进制表示什么,什么是十六进制表达式0x80000000在C语言的枚举声明中的含义...
  3. android plurals用法(单复数),移动智能终端开发技术题库
  4. C语言-大数次幂运算方法
  5. 17:计算三角形面积
  6. 2023年AP宏观经济学考试变化你都了解吗?考纲部分有所调整
  7. 智能电视app安装步骤启动及卸载
  8. Android gradle配置签名文件
  9. 数字化浪潮下,消费金融公司的金融科技之路
  10. linux如何运行c程序命令