说到做到!(三)

简介: MQTT 协议的全称是 Message Queuing Telemetry Transport,翻译为消息队列传输探测,它是 ISO 标准下的一种基于发布 - 订阅模式的消息协议,它是基于 TCP/IP 协议簇的,它是为了改善网络设备硬件的性能和网络的性能来设计的。MQTT 一般多用于 IoT 即物联网上,广泛应用于工业级别的应用场景,比如汽车、制造、石油、天然气等。

消息类型

发布

当 MQTT client 在连接到 broker 之后就可以发送消息了,MQTT 使用的是基于 topic 主题的过滤。每条消息都应该包含一个 topic ,broker 可以使用 topic 将消息发送给感兴趣的 client。除此之外,每条消息还会包含一个负载(Payload),Payload 中包含要以字节形式发送的数据。

MQTT 是数据无关性的,也就是说数据是由发布者 - publisher 决定要发送的是 XML 、JSON 还是二进制数据、文本数据。

MQTT 中的 PUBLISH 消息结构如下。

微信图片_20220416181913.png

  • Packet Identifier:这个 PacketId 标识在 client 和 broker 之间唯一的消息标识。packetId 仅与大于零的 Qos 级别相关。
  • TopicName:主题名称是一个简单的字符串,/ 代表着分层结构。
  • Qos:这个数字表示的是服务质量水平,服务质量水平有三个等级:0、1 和 2,服务级别决定了消息到达 client 或者 broker 的保证类型,来决定消息是否丢失。
  • RetainFlag:这个标志表示 broker 将最近收到的一条 RETAIN 标志位为true的消息保存在服务器端(内存或者文件)。

MQTT 服务器只会为每一个 Topic 保存最近收到的一条 RETAIN 标志位为true的消息。也就是说,如果MQTT 服务器上已经为某个 Topic 保存了一条 Retained 消息,当客户端再次发布一条新的 Retained 消息时,那么服务器上原来的那条消息会被覆盖。

  • Payload:这个是每条消息的实际内容。MQTT 是数据无关性的。可以发送任何文本、图像、加密数据以及二进制数据。
  • Dupflag:这个标志表示该消息是重复的并且由于预期的 client 或者 broker 没有确认所以重新发送了一次。这个标志仅仅与 Qos 大于 0 相关。

当 client 向 broker 发送消息时,broker 会读取消息,根据 Qos 的级别进行消息确认,然后处理消息。处理消息其实就是确定哪些 subscriber 订阅了 topic 并将消息发送给他们。

微信图片_20220416181921.png

最初发布消息的 client 只关心将 PUBLISH 消息发送给 broker,一旦 broker 收到 PUBLISH 消息,broker 就有责任将其传递给所有 subscriber。发布消息的 client 不会知道是否有人对发布的消息感兴趣,同时也不知道多少 client 从 broker 收到了消息。

订阅

client 会向 broker 发送 SUBSCRIBE 消息来接收有关感兴趣的 topic,这个 SUBSCRIBE 消息非常简单,它包含了一个唯一的数据包标识和一个订阅列表。

微信图片_20220416181924.png

  • Packet Identifier:这个 PacketId 和上面的 PacketId 一样,都表示消息的唯一标识符。
  • ListOfSubscriptions:SUBSCRIBE 消息可以包含一个 client 的多个订阅,每个订阅都会由一个 topic 和一个 Qos 构成。订阅消息中的 topic 可以包含通配符。

确认消息

client 在向 broker 发送 SUBSCRIBE 消息后,为了确认每个订阅,broker 会向 client 发送 SUBACK 确认消息。这个 SUBACK 包含原始 SUBSCRIBE 消息的 packetId 和返回码列表。

微信图片_20220416181928.png

其中

  • Packet Identifier :这个数据包标识符和 SUBSCRIBE 中的相同。
  • ReturnCode:broker 为每个接收到的 SUBSCRIBE 消息的 topic/Qos 对发送一个返回码。例如,如果 SUBSCRIBE 消息有五个订阅消息,则 SUBACK 消息包含五个返回码作为响应。

到现在我们已经探讨过了三种消息类型,发布 - 订阅 - 确认消息,这三种消息的示意图如下。

微信图片_20220416181931.png

退订

SUBSCRIBE 消息对应的是 UNSUBSCRIBE 消息,这条消息发送后,broker 会删除关于 client 的订阅。所以,UNSUBSCRIBE 消息与 SUBSCRIBE 消息类似,都具有 packetId 和 topic 列表。

微信图片_20220416181934.png

确认退订

取消订阅也需要 broker 的确认,此时 broker 会向 client 发送一个 UNSUBACK 消息,这个 UNSUBACK 消息非常简单,只有一个 packetId 数据标识符。

微信图片_20220416181937.png

退订和确认退订的流程如下。

微信图片_20220416181941.png

当 client 收到来自 broker 的 UNSUBACK 消息后,就可以认为 UNSUBSCRIBE 消息中的订阅被删除了。

聊聊 Topic

聊了这么多关于 MQTT 的内容,但是我们还没有好好聊过 Topic。在 MQTT 中,Topic 是指 broker 为每个连接的 client 过滤消息的 UTF-8 字符串。Topic 是一种分层的结构,可以由一个或者多个 Topic 组成。每个 Topic 由 / 进行分割。

微信图片_20220416181945.png

与传统的消息队列相比,MQTT Topic 非常轻量级,client 在发布或订阅之前不需要先创建所需要的 Topic,broker 在接收每个 Topic 前不用进行初始化操作。

通配符

当客户端订阅 Topic 时,它可以订阅已发布消息的确切 Topic,也可以使用通配符来同时订阅多个 Topic。通配符有两种:单级和多级

单级通配符

单级通配符可以替换 Topic 的一个级别,+ 号代表 Topic 中的单级通配符。

微信图片_20220416181949.png

如果 Topic 包含任意字符串而不是通配符,则任何 Topic 都能够和单级通配符匹配。例如

myhome/groundfloor/+/temperature 就有下面这几种匹配方式。

微信图片_20220416181953.png

多级通配符

多级通配符涵盖多个 Topic,# 代表 Topic 中的多级通配符。为了让 broker 能够确定和哪些 Topic 匹配,多级通配符必须作为 Topic 中的最后一个字符放置,并以 / 开头。

微信图片_20220416181957.png

下面是 myhome/groundfloor/# 的几个例子

微信图片_20220416182000.png

当 client 订阅带有多级通配符的 Topic 时,不论 Topic 有多长多深,它都会收到通配符之前 Topic 的所有消息。如果你只将 Topic 定义为 # 的话,那么你将会收到所有的消息。

总结

这篇文章的起因是有小伙伴留言说想要了解一下 MQTT 协议,因为之前没有了解过这个协议,更别谈写了。MQTT 相当于是舒适区之外的新东西,是值得花时间研究的,这也是我写这篇文章的原因。

文中可能有写的不太好或者有勘误的地方,大家多多提出建设性意见呀~ 我们下篇文章见。

相关实践学习
消息队列RocketMQ版:基础消息收发功能体验
本实验场景介绍消息队列RocketMQ版的基础消息收发功能,涵盖实例创建、Topic、Group资源创建以及消息收发体验等基础功能模块。
消息队列 MNS 入门课程
1、消息队列MNS简介 本节课介绍消息队列的MNS的基础概念 2、消息队列MNS特性 本节课介绍消息队列的MNS的主要特性 3、MNS的最佳实践及场景应用 本节课介绍消息队列的MNS的最佳实践及场景应用案例 4、手把手系列:消息队列MNS实操讲 本节课介绍消息队列的MNS的实际操作演示 5、动手实验:基于MNS,0基础轻松构建 Web Client 本节课带您一起基于MNS,0基础轻松构建 Web Client
相关文章
|
Web App开发 开发者
利用chrome控制台调试post请求
利用chrome控制台调试post请求
263 0
|
6月前
|
SQL XML Java
ruoyi若依框架@DataScope注解使用以及碰到的一些问题
ruoyi若依框架@DataScope注解使用以及碰到的一些问题
1433 0
|
5月前
|
SQL 分布式计算 DataWorks
DataWorks操作报错合集之遇到实时同步任务中字段错位和类型不匹配,该如何解决
DataWorks是阿里云提供的一站式大数据开发与治理平台,支持数据集成、数据开发、数据服务、数据质量管理、数据安全管理等全流程数据处理。在使用DataWorks过程中,可能会遇到各种操作报错。以下是一些常见的报错情况及其可能的原因和解决方法。
75 0
|
4月前
|
C语言 C++
【C++】string模拟实现(下)
本文档介绍了自定义`string`类的一些关键功能实现,包括`reserve()`用于内存管理,`push_back()`和`append()`添加字符或字符串,运算符`+=`的重载,以及`insert()`, `erase()`进行插入和删除操作。此外,还涵盖了`find()`查找函数,字符串的比较运算符重载,`substr()`获取子串,`clear()`清除内容,以及流插入和提取操作。常量`npos`用于表示未找到的标记。文档以代码示例和运行结果展示各功能的使用。
|
XML 存储 人工智能
分享:包括 AI 绘画在内的超齐全免费可用的API 大全
我给大家整理了超级齐全的免费可用 API,包括 AI 绘画在内,有需要的小伙伴赶紧收藏了。
1225 0
分享:包括 AI 绘画在内的超齐全免费可用的API 大全
|
JavaScript UED
vue利用双向数据绑定实现多个输入框回显并且加入条件
vue利用双向数据绑定实现多个输入框回显并且加入条件
167 0
|
Java
Java中String类案例实现
String类简单案例实现
380 0
Java中String类案例实现
|
算法
基础算法练习200题07、编框
基础算法练习200题07、编框
92 0
springboot+mybatisplus+layui+restful实现弹出层异步提交表单
springboot+mybatisplus+layui+restful实现弹出层异步提交表单
195 0
|
存储 XML 缓存
Activiti原理分析(一)从一个简单流程开始
本系列文章将基于 Activiti 6 源代码对 Activiti 的原理进行深入剖析,让读者快速知其然,同时知其所以然。 第一篇文章将分析一个简单流程在 Activiti 中的执行流程,借此把 Activiti 底层的一些概念快速梳理一遍,让读者对 Activiti 的底层实现有个大概了解,知晓每张表的作用。内容都是笔者从源码里分析出来或者核对过的,比一般的文档更加翔实靠谱。
3613 2
Activiti原理分析(一)从一个简单流程开始