Linux--MQTT(二)通信基本原理

一、MQTT 通信基本原理

MQTT 是一种基于 客户端 - 服务端 架构的消息传输协议,所以在 MQTT 协议通信中,有两个最为重要的角色,它们便是服务端 客户端
举例:若开发板向“芯片温度”这一主题发布消息,那么服务端接收到消息后会将消息转发给订阅了“芯片温度”的所有客户端。

服务端

MQTT 服务端通常是一台服务器( broker ),它是 MQTT 信息传输的枢纽,负责将 MQTT 客户端发送来的信息传递给 MQTT 客户端; MQTT 服务端还负责管理 MQTT 客户端,以确保客户端之间的通讯顺畅, 保证 MQTT 信息得以正确接收和准确投递。

客户端

MQTT 客户端可以向服务端发布信息,也可以从服务端收取信息;我们把客户端发送信息的行为称为 “发布”信息。而客户端要想从服务端收取信息,则首先要向服务端“订阅”信息。“订阅”信息这一操作很像我们在使用微信时“关注”了某个公众号,当公众号的作者发布新的文章时,微信官方会向关注了该公众号的所有用户发送信息,告诉他们有新文章更新了,以便用户查看。

MQTT 主题

客户端想要从服务器获取信息,首先需要订阅信息,那客户端如何订阅信息呢?这里我们要引入“主题(Topic )”的概念,“主题”在 MQTT 通信中是一个非常重要的概念,客户端发布信息以及订阅信息都是围绕“主题”来进行的,并且 MQTT 服务端在管理 MQTT 信息时,也是使用“主题”来控制的。
客户端发布消息时需要为消息指定一个“主题”,表示将消息发布到该主题;而对于订阅消息的客户端来说,可通过订阅“主题”来订阅消息,这样当其它客户端或自己(当前客户端)向该主题发布消息时,MQTT 服务端就会将该主题的信息发送给该主题的订阅者(客户端)。
值得注意的是, MQTT 客户端在通信时,角色往往不是单一的,一个客户端既可以作为信息发布者也可以同时作为信息订阅者。如下图所示:

MQTT 发布/订阅特性

MQTT 通信的核心枢纽是 MQTT 服务端,它负责将 MQTT 客户端发送来的 信息传递给 MQTT 客户端,还负责管理 MQTT 客户端,以确保客户端之间的通讯顺畅,保证 MQTT 信息得以正确接收和准确投递。
客户端相互独立: MQTT 客户端是一个个独立的个体,它们无需了解彼此的存在,依然可以实现 信息交流。
时间上可异步: MQTT 客户端在发送和接收信息时无需同步。这一特点对物联网设备尤为重要, 前面我们也介绍了,MQTT 从诞生之初就是专为低带宽、高延迟或不可靠的网络而设计的,高延 迟和不可靠网络必然就会导致时间上的异步;物联网设备在运行过程中发生意外掉线是非常正常 的情况,我们使用上面的实例二的场景来作说明,当开发板在运行过程中,可能会由于突然断电 (假设开发板是通过电源适配器供电的)导致掉线,这时开发板会断开与 MQTT 服务端的连接。 假设此时我们的手机客户端向开发板客户端所订阅的“LED 控制”主题发布了信息,而开发板恰 恰不在线,这时,MQTT 服务端可以将“ LED 控制”主题的新信息保存,待开发板客户端再次上线后,服务端再将“LED 控制”信息推送给开发板。所以这就必然导致了,手机发送信息与开发板接收信息在时间上是异步的。

二、连接MQTT服务端

MQTT 客户端之间想要实现通信,必须要通过 MQTT 服务端。所以,客户端无论是发布信息还是订阅信息都必须先连接到服务端。下面我们来看一下,客户端连接服务端的详细过程。

MQTT 客户端连接服务端总共包含了两个步骤:

①、首先客户端需要向服务端发送连接请求,这个连接请求实际上就是向服务端发送一个 CONNECT报文,也就是发送了一个 CONNECT 数据包。
②、 MQTT 服务端收到连接请求后,会向客户端发送连接确认。连接确认实际上是向客户端发送一个CONNACK 报文,也就是 CONNACK 数据包。

CONNECT 报文

在上面的描述中我们看到, MQTT 客户端要想连接服务端,首先要向服务端发送 CONNECT 报文。如 果此 CONNECT 报文的格式或内容不符合 MQTT 规范,则服务器会拒绝客户端的连接请求。
一个CONNECK报文内容举例如下:
所谓报文就是一个数据包, MQTT 报文组成分为三个部分:固定头( Fixed header )、可变头( Variable header)以及有效载荷( Payload ,消息体)。这里我们简单地介绍一下:
固定头( Fixed header ): 存在于所有 MQTT 报文中,固定头中有报文类型标识,可用于识别是哪 种 MQTT 报文,譬如该报文是 CONNECT 报文还是 CONNACK 报文,亦或是其它类型报文。
可变头( Variable header ): 存在于部分类型的 MQTT 报文中,报文的类型决定了可变头是否存 在及其具体的内容。
消息体( Payload ): 存在于部分类型的 MQTT 报文中, payload 就是消息载体的意思。
在上图中的报文内容有:
clientId-- 客户端 id
clientId MQTT 客户端的标识,也就是 MQTT 客户端的名字, MQTT 服务端可通过 clientId 来区分不同的客户端,MQTT 服务端用该标识来识别客户端。
keepAlive-- 心跳时间间隔
keepAlive 其实是指定了心跳时间间隔,也就是客户端向服务端发送心跳包的时间间隔。譬如 keepAlive=60 ,表示告诉服务端,客户端将会每隔 60 秒左右向服务端发送心跳包。
cleanSession-- 清除会话
cleanSession 设置为 1 ,表示此次连接将创建一个新的临时会话,在客户端断开后,这个会话会自动销毁。而 cleanSession 设置为 0 ,表示创建一个持久性会话,在客户端断开连接时,会话仍然保持并保存离线消息,直到会话超时注销。

CONNACK 报文

                  

returnCode-- 连接返回码
当服务端收到了客户端的连接请求后,会向客户端发送 returnCode( 连接返回码 ) ,用来说明连接情况。 如果客户端与服务端成功连接,则返回数字“0 ”。如果未能成功连接,返回码将会是一个非零的数字。
sessionPresent
CONNACK 报文的 sessionPresent CONNECT 报文的 cleanSession 相互配合。其作用是客户端发送连接请求时,服务端告知客户端有没有保存会话状态。这个被服务端保存的会话状态是来自于上一 次客户端连接时,譬如离线消息以及上一次连接时客户端所订阅的主题。
若基于TCP协议则连接建立过程如下:
客户端                       服务器|                           ||---- TCP SYN ------------> ||                           ||<--- TCP SYN-ACK --------- ||                           ||---- TCP ACK ------------> ||  (TCP 连接建立)          ||                           ||---- MQTT CONNECT -------> ||                           ||<--- MQTT CONNACK -------- ||  (MQTT 连接建立)         |

三、断开连接

MQTT 客户端连接到服务端之后,在后续的通信过程中,如果客户端想要断开与服务端的连接,此 时客户端可以主动向服务端发送一个 DISCONNECT 报文来断开与服务端的连接,如下图所示:

四、发布消息、订阅主题与取消订阅主题

当客户端连接到服务端之后,便可以发布消息或订阅主题了。

PUBLISH–发布消息

当客户端连接到服务端之后,就可以向服务端发布消息了,每条发布的消息必须指定一个“主题”,表示向某主题发布消息;MQTT 服务端可以通过主题来确定将消息转发给哪些客户端(订阅了该主题的客户端)。
MQTT 客户端向服务端发布消息其实就是向服务端发送一个 PUBLISH 报文,服务端收到客户端发送过来的 PUBLISH 报文之后,会向发送方回复一个报文。根据 QoS 的不同,回复的报文类型也是不同的,并且 整个发布消息的过程也将会有所区别;譬如对于 QoS=1 时,客户端向服务端发送 PUBLISH 报文,服务端 收到 PUBLISH 报文之后会向发送方回复 PUBACK 报文;而对于 QoS=2 的情况,将会更加复杂。
下图是 PUBLISH 报文包含的信息:
packetId-- 报文标识符
报文标识符可用于对 MQTT 报文进行标识(识别不同的报文)。不同的 MQTT 报文所拥有的标识符不同。MQTT 设备可以通过该标识符对 MQTT 报文进行甄别和管理, MQTT 协议内部使用的标识符。请注意:
报文标识符的内容与 QoS 级别有密不可分的关系。只有 QoS 级别大于 0 时,报文标识符才是非零数值。如果 QoS 等于 0 ,报文标识符为 0
topicName-- 主题名字
这个就是发布消息时对应的主题的名字,这是一个字符串,譬如上图中 topicName= myTopic ”,表示会将消息发布到“myTopic ”这个主题。
payload-- 有效载荷
有效载荷是我们希望通过 MQTT 所发送的实际内容。我们可以使用 MQTT 协议发送字符串文本,图像等格式的内容。这些内容都是通过有效载荷所发送的。
qos-- 服务质量等级
QoS Quality of Service )表示 MQTT 消息的服务质量等级。 QoS 有三个级别: 0 1 2 QoS 决定 MQTT 通信有什么样的服务保证。
retain-- 保留标志
在默认情况下,当客户端订阅了某一主题后,并不会马上接收到该主题的信息。因为客户端订阅该主题 之后,并没有其它客户端向该主题发布消息;只有在客户端订阅该主题后,服务端接收到该主题的新消息时,服务端才会将最新接收到的该主题消息推送给客户端。
但是在有些情况下,我们需要客户端在订阅了某一主题后马上接收到一条该主题的信息。这时候就需要用到保留标志这一信息。
dup-- 重发标志
dup 标志指示此消息是否重复。
MQTT 报文的接收方没有及时向报文发送发回复 确认收到报文 时,发送方会以为对方没有收到信息,会再次重复发送 MQTT 报文(譬如客户端向服务端发送 PUBLISH 报文,服务端收到 PUBLISH 报文之后需要向客户端回复一个 PUBACK 报文,如果客户端没收到 PUBACK 报文,则会认为服务端可能没接收到自己发送的报文,将会再次发送 PUBLISH 报文)。在重复发送 MQTT 报文时,发送方会将此“dup--重发标志”设置为 true 请注意,重发标志只在 QoS 级别大于 0 时使用。

SUBSCRIBE--订阅主题

客户端要想接收消息,首先要订阅该消息的主题。这样,当有客户端向该主题发布消息后,订阅了该主题的客户端就能接收到消息了。
客户端要想订阅主题,首先要向服务端发送主题订阅请求。客户端是通过向服务端发送 SUBSCRIBE 报文来实现这一请求的。该报文包含有一系列“订阅主题名”。请留意,一个 SUBSCRIBE 报文可以包含有单个或者多个订阅主题名。也就是说,一个 SUBSCRIBE 报文可以用于订阅一个或者多个主题。服务端会根据 SUBSCRIBE 中的 QoS 来提供相应的服务保证。
SUBACK 报文包含有“订阅返回码”和“报文标识符”这两个信息。
returnCode-- 订阅返回码
客户端向服务端发送订阅请求后,服务端会给客户端返回一个订阅返回码。在之前的讲解中我们说过,客户端可通过一个 SUBSCRIBE 报文发送多个主题的订阅请求。服务端会针对 SUBSCRIBE 报文中的所有订阅主题来逐一回复给客户端一个返回码。这个返回码的作用是告知客户端是否成功订阅了主题。

UNSUBSCRIBE--取消订阅主题

客户端订阅了某一主题之后,可以随时取消订阅, MQTT 协议提供了这样的操作。
客户端通过向服务端发送一个 UNSUBSCRIBE 报文来取消订阅主题,当服务端接收到 UNSUBSCRIBE报文后,会向发送发回复一个 UNSUBACK 报文(取消订阅确认报文),如下图所示:

五、主题的进阶

主题的基本形式就是一个字符串,譬如: "myTopic" "currentTemp" "LEDControl"等,但是有几个点需要大家注意一下:

1、主题形式

主题是区分大小写的。 所以 "LEDControl" "ledControl" 是两个不同的主题。
主题可以使用空格。 譬如 "LED Control" ,虽然主题允许使用空格,但是笔者建议大家尽量不要使用空格。
不要使用中文主题。 虽然有些 MQTT 服务器支持中文主题,但是绝大部分 MQTT 服务器是不支持中文主题的,所以大家不要使用中文主题,而是使用 ASCII 字符来作为 MQTT 主题。

2、主题分级

MQTT 主题可以是一个简单的字符串,譬如: "myTopic" "currentTemp" "LEDControl" ,事实上, MQTT协议为了更好的对主题进行管理和分类,支持主题分级,对主题进行分级处理,各个级别之间使用" / " 符号进行分隔。如下所示:
"home/sensor/led/brightness"
在以上示例中一共有四级主题,分别是第 1 home 、第 2 sensor 、第三级 led 、第 4 brightness 。 主题的每一级至少需要一个字符;而只有一个简单字符串的主题,如"myTopic" "currentTemp"、 "LEDControl",这些都是单一级别的主题。需要注意的是,主题名称不要使用 " / " 开头。

3、主题通配符

当客户端订阅主题时,可以使用通配符同时订阅多个主题。通配符只能在订阅主题时使用,分为单级通配符和多级通配符。

4、主题应用注意事项

$ 开头的主题
$ 号开头的主题是 MQTT 服务端系统保留的特殊主题,客户端不可随意订阅或向其发布信息
不要使用“ / ”作为主题开头
尽量不要使用“ / ”作为主题的开头,这样做没有什么意义,而且额外产生一个没有用处的主题级别。
主题中不要使用空格
虽然, MQTT 支持在主题中使用空格,但是我们应该尽量避免使用空格。
保持主题简洁明了
MQTT 是一种轻量级的通讯协议,它常用于网络带宽受限的环境,因此我们应尽量让主题简洁明了,从而让设备间交互的内容更加简洁,以更好的适应网络带宽受限的环境。
主题中尽量使用 ASCII 字符
虽然有些 MQTT 设备支持 UTF-8 字符作为 MQTT 主题,建议在主题中尽量使用 ASCII 字符。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/28174.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

cocos开发的时候 wx.onShow在vscode里面显示红色

这个函数是在微信小游戏平台才会用到。 cocos识别不到wx这个变量。 可以改成下面的写法。 只要在变量前面加一个globalThis.就能识别这个变量了。也不报错了。 搞死强迫症了。orz 欢迎大家来玩我的微信小游戏。多多提意见啊。

欧阳修,仕途波澜中的文坛巨匠

欧阳修&#xff0c;字永叔&#xff0c;号醉翁、六一居士&#xff0c;生于北宋真宗景德四年&#xff08;公元1007年&#xff09;&#xff0c;卒于北宋神宗熙宁五年&#xff08;公元1072年&#xff09;&#xff0c;享年65岁。他是北宋时期著名的文学家、史学家&#xff0c;也是唐…

计算机缺失d3dcompiler_43.dll怎么办,介绍5种靠谱的解决方法

在电脑使用过程中&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中之一就是“找不到d3dcompiler43.dll”的错误。那么&#xff0c;d3dcompiler43.dll到底是什么&#xff1f;为什么会出现丢失的情况&#xff1f;它对计算机有什么具体影响&#xff1f;如何解决这个问题&a…

数据库系统概念(第七周 第二堂)(E-R模型转关系模式)

前言 前一堂课我们深入研究了E-R模型的画法和要点&#xff0c;学习E-R模型肯定是为了给数据库表格设计提供帮助。数据库表格设计就是关系模式设计&#xff0c;数据库表就是关系模式的实例化。所以本堂课&#xff0c;我们来看E-R模型如何转为关系模式。 转化原则 转化步骤 转…

[Vulnhub]Solid-State POP3邮件服务(James)+rbash逃逸

信息收集&SSH Server IP addressPorts Open192.168.8.100TCP:22,25,80,110,119,4555 Nmap 扫描: $ nmap -p- 192.168.8.100 --min-rate 1000 -sC -sV 结果: Host is up (0.00061s latency). Not shown: 65529 closed tcp ports (conn-refused) PORT STATE SERVICE…

phpStudy安装sqli-labs

phpStudy安装sqli-labs git地址&#xff1a;https://github.com/Audi-1/sqli-labs 点击管理–>根目录 将git下载的sqli-labs文件放进去并解压 进入sql-connections修改 修改db-creds.inc文件为自己数据库的账号密码 更改php版本为5.*&#xff0c;因为这个程序只能在php 5.…

[Golang] go-kit 介绍和使用 (微服务实现工具)

文章目录 1.go-kit 介绍1.1 go-kit 三层结构 2.go-kit 实例 1.go-kit 介绍 go-kit是一个分布式的开发工具集&#xff0c;在大型的组织&#xff08;业务&#xff09;中可以用来构建微服务&#xff0c;其解决了分布式系统中大多数常见问题&#xff0c;因此&#xff0c;使用者可以…

Paragon NTFS for Mac 15软件下载-详细安装教程视频

​Paragon NTFS for Mac是Mac平台上一款非常优秀的读写工具&#xff0c;可以在Mac OS X中完全读写、修改、访问NTFS硬盘、U盘等外接设备的文件。这款软件最大的亮点简书可以让我们读写 NTFS 分区&#xff0c;因为在Mac OS X 系统上&#xff0c;默认状态下我们只能读取NTFS 分区…

Spring-kafka消费者消费的一些问题

前言 Spring Kafka 无缝集成了 Spring Boot、Spring Framework 及其生态系统中的其他项目&#xff0c;如 Spring Cloud。通过与 Spring Boot 的自动配置结合&#xff0c;开发者可以快速启动和配置 Kafka 相关的功能。无需编写大量样板代码即可实现 Kafka 的生产和消费功能&…

【源码】16国语言交易所源码/币币交易+期权交易+秒合约交易+永续合约+交割合约+新币申购+投资理财/手机端uniapp纯源码+PC纯源码+后端PHP

测试环境&#xff1a;Linux系统CentOS7.6、宝塔面板、Nginx、PHP7.3、MySQL5.6&#xff0c;根目录public&#xff0c;伪静态laravel5&#xff0c;开启ssl证书 语言&#xff1a;16种&#xff0c;看图 这套带前端uniapp纯源码&#xff0c;手机端和pc端都有纯源码&#xff0c;后…

list集合自定义排序

一、基本类型排序 1.list中只有数字或字符串 //升序排序 List<T> ,T为数字或字符串 Collections.sort(list); //降序排序 Collections.sort(list,Collections.reverseOrder());2.list中为对象 基于jdk.18 import lombok.Data;Data public class User {private int i…

Linux下Shell脚本基础知识

主要参考视频&#xff1a; 这可能是B站讲的最好的Linux Shell脚本教程&#xff0c;3h打通Linux-shell全套教程&#xff0c;从入门到精通完整版_哔哩哔哩_bilibili 主要参考文档&#xff1a; Shell 教程 | 菜鸟教程 (runoob.com) Bash Shell教程 (yiibai.com) 先用视频入门&…

基于springboot实现火锅店管理系统项目【项目源码+论文说明】

基于springboot实现火锅店管理系统演示 摘要 传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&#xff0c;在计算机上安装火锅店管理系统软件来…

编译一个叫:未来的IDE-Zed编辑器(Windows平台)

一、前言 截止到2024-6-15&#xff0c;Zed官方并未给出Windows的二进制安装包&#xff0c;如果想在Windows平台使用的话需要自己编译&#xff0c;我是如何编译的请随我道来&#xff0c;有兴趣的码友可以尝试下&#xff0c;在下可不敢保证各位码友按我这方法能100%编译出来&…

【JavaEE进阶】——利用框架完成功能全面的图书管理系统

目录 &#x1f6a9;项目所需要的技术栈 &#x1f6a9;项目准备工作 &#x1f388;环境准备 &#x1f388;数据库准备 &#x1f6a9;前后端交互分析 &#x1f388;登录 &#x1f4dd;前后端交互 &#x1f4dd;实现服务器代码 &#x1f4dd;测试前后端代码是否正确 &am…

一些硬件知识(十)

MOS管当开关控制时&#xff0c;一般用PMOS做上管&#xff0c;NMOS做下管 细说MOS管知识-MOS管高端驱动与低端驱动解析和原理及区别_高端功率 mos 管是什么意思-CSDN博客 PMOS管&#xff1a; PMOS管的源极&#xff08;Source&#xff09;通常连接到正电源&#xff08;Vcc&#…

西门子学习笔记15 - 位逻辑操作的学习

1、点动操作&#xff08;按下按钮就启动松开就停止&#xff09; 2、自锁电路&#xff08;可以自己保持的状态除非常闭停止按下&#xff09; 3、取反操作&#xff08;顾名思义就是反过来1就变成0&#xff0c;0就变成1&#xff09; 4、置为复位&#xff08;置位之后如果不复位的话…

SpringBoot自定义Starter及原理分析

目录 1.前言2.环境3.准备Starter项目4.准备AutoConfigure项目4.1 准备类HelloProperties4.2 准备类HelloService4.3 准备类HelloServiceAutoConfiguration4.4 创建spring.factories文件并引用配置类HelloServiceAutoConfiguration4.5 安装到maven仓库 5.在其他项目中引入自定义…

困惑度作为nlp指标的理解示例

为了更清晰地说明困惑度的计算过程以及如何通过困惑度判断模型的优劣&#xff0c;我们可以通过一个简单的例子来演示。假设我们有一个非常简单的文本语料库和两个基础的语言模型进行比较。 示例文本 假设我们的文本数据包括以下两个句子&#xff1a; “cat sits on the mat”…

计算机网络:网络层 - 路由选择协议

计算机网络&#xff1a;网络层 - 路由选择协议 路由器的结构路由选择协议概述自治系统 AS内部网关协议路由信息协议 RIP距离向量算法RIP报文格式收敛问题 开放最短路径优先 OSPF基本工作原理自治系统分区 外部网关协议BGP-4 路由器的结构 如图所示&#xff0c;路由器被分为路由…