MQTT客户端、代理(broker)和连接建立

news2025/1/16 11:22:41

在前篇文章(http://t.csdnimg.cn/IamPz)中,介绍了发布/订阅架构和MQTT如何据此交换信息,其中的关键概念是:

  • 发布/订阅架构触耦了负责发布信息的客户端(发布者)和负责接收信息的客户端(订阅端)。
  • MQTT使用主题确定哪个客户端(订阅者)应该接收信息。主题是一个层级性的字符串,可以用来过滤和路由消息。

接下来,将深入MQTT的世界,介绍MQTT代理(broker)和MQTT的连接。

MQTT客户端和MQTT代理(broker)

MQTT中的两个关键概念是客户端和代理(broker)。一个MQTT客户端可以是任何一个可以通过网络连接到MQTT代理(broker)的运行了MQTT库的设备。发布者和订阅者标签是指发布或订阅消息的客户端。另外,MQTT代理(broker),负责接收、过滤消息,并将消息发送给订阅消息的客户端。代理(broker)同样负责客户端认证和授权,并通过持久会话保存所有客户端的会话数据。

什么是MQTT客户端

在IoT场景中,一个MQTT客户端通常代理一个发布者或订阅者。一个发布者客户端发送信息,而订阅者客户端接收信息。但是,一个MQTT客户端可既是发布者又是订阅者。
一个MQTT客户端可以是任意设备,从一个微控制器到一个大的服务器,运行着MQTT库且通过网络连接到MQTT代理(broker)。
一个MQTT库是一个实现了MQTT协议的软件模块或包,为设备或程序提供一个接口和MQTT通信。这些库可以更轻松的将MQTT支持添加到应用程序和设备中,而无需从头开始实现协议。

MQTT客户端库对很多编辑语言和平台都可用,比如安卓、C、C++、C#、Go、iOS、Java、JavaScript等。

MQTT客户端可以是运行用于测试目的的图形界面MQTT客户端的典型计算机。MQTT被设计为在TCP/IP协议之上工作,因此任何使用TCP/IP并实现MQTT协议的设备都是MQTT客户端。MQTT协议的客户端实现简单明了,非常适合小型设备。

什么是MQTT代理(broker)

MQTT代理(broker)是发布/订阅消息传递系统中的中心枢纽,它接收来自发布者的消息并将其分发给订阅者。在管理MQTT客户端之间的通信流和确保消息可靠的分发上,它扮演着重要的角色。
MQTT代理(broker)的功能包括以下方面:

  1. 处理大量的并发连接:依据实现的不同,代理可以处理数百万个MQTT客户端并发连接。它通过弥合不同设备、网络和软件系统之间的差距来实现它们之间的通信。
  2. 过滤和路由消息:代理(broker)依赖订阅主题过滤消息和确定哪个客户端接收消息。
  3. 身份验证和授权:依据客户端提供的凭据,代理(broker)负责身份验证和授权。代理是可扩展的,便于自定义身份验证、授权和集成到后端系统中。除了身份验证和授权,代理可提供其他安全功能,比如消息传输加密和接入控制清单。
  4. 可扩展性、集成和监控:一个MQTT客户端必须可扩展来处理大量的消息、客户端,能够集成到后端系统,容易监控且具有抗故障能力。为了满足这些要求,MQTT代理(broker)必须使用最先进的事件驱动网络处理,一个开放的扩展系统和标准监视提供程序。代理(broker)也可以提供其他先进的功能来管理、监控MQTT系统,比如消息过滤、消息持久化和实时分析。

另外,一个MQTT代理(broker)支持集群,允许多个代理(实例)一同工作来处理大量的客户端和消息。
上面已经讨论了MQTT代理(broker)和其责任,接下来更进一步的了解MQTT客户端是如何建立和代理(broker)的连接。

MQTT客户端和代理(broker)如何建立连接

MQTT协议的一个关键功能是其在IoT设备之间交换消息的高效和轻量级方法。这种通信的基础是MQTT连接,它使设备能够安全可靠的与MQTT代理(broker)交换数据。在这一部分中,我们会探究MQTT连接建立的过程和涉及到的不同参数。通过理解MQTT连接如何工作,就可以优化你的IoT部署,以获得更好的性能、安全性和可扩展性。
MQTT协议是基于TCP/IP,意味着客户端和代理(broker)必须有TCP/IP栈。
MQTT的连接永远在一个客户端和一个代理(broker)之间,客户端之间决不会直接相连。为了初始化连接,客户端发送“CONNECT”信息到代理(broker),代理会使用“CONNACK”消息和状态代码进行响应。一旦连接建立,代理(broker)会保持这个连接直到客户端发送一条断开连接指令或连接中断。
MQTT CONNECT.png
本部分会探究通过NAT的MQTT连接,以及MQTT客户端如何通过向代理发送CONECT消息来初始化连接。我们会深入了解MQTT CONNECT命令消息的细节,聚集一些关键选项,包括客户端ID(ClientId)、清除会话、用户名/密码、遗嘱消息和保活等。另外,我们会讨论代理对CONNECT的响应消息,即一条CONNACK消息,该消息包含两个数据条目:会话存在标志和连接返回代码。

通过NAT的MQTT连接

在许多情况下,MQTT客户端位于使用网络地址转换(NAT)将专用网络地址(例如192.168.x.x或10.0.x.x)转换为面向公共地址的路由后面,正如前面提到的,MQTT客户端通过发送CONNECT消息到代理(broker)来启动连接。由于代理(broker)有一个公共地址且保持连接打开以启用消息的双向发送和接收(初始化连接后),位于NAT路由器后面的MQTT客户端不会遇到任何困难。
对于那些不知道的人,NAT是一种常见的网络技术,路由器用来允许私有网络内的设备通过一个公共IP连接到互联网。NAT的工作原理是将私有网络上设备的IP地址转换为路由器的公共IP地址,反之亦然。

在MQTT中,位于NAT路由器后面的客户端依然可以和MQTT代理(broker)通信,因为代理(broker)有一个公共地址,能够和客户端通过NAT连接。但是,通过NAT,一些潜在的问题可能出现,比如配置端口转发或打开防火墙端口以允许流量进来到达代理。另外,一些NAT实现可能在并发连接建立上存在限制,会影响MQTT系统的扩展性。

现在我们理解了位于NAT之后的MQTT客户端和MQTT代理(broker)如何建立连接,接下来更进一步连接MQTT CONNECT命令和它的内容。

MQTT客户端如何通过CONNECT消息初始化连接

现在让我们检查下MQTT CONNECT命令消息,也就是客户端发送到代理(broker)来初始化连接的。如果此消息格式不正确,或者打开网络套接字和发送CONNECT消息之间间隔过长,那么代理(broker)将终止连接以阻止可能降低代理速度的恶意客户端。除了MQTT3.1.1规范中指定的其他详细外,正常的MQTT3客户端还会发送以下内容。让我们关注一个关键选项。
image.png
虽然MQTT库的用户可能会发现CONNECT消息中的某些信息有用,但某些细节可能与库的实现者更相关。为了对消息中包含的所有信息有一个完整的理解,参照 MQTT 3.1.1 specification.
让我们看下MQTT CONNECT包中的一些元素,比如ClinetId、Clean Session、Username/Password、Will Message、Keep Alive等。

MQTT CONNECT包中的ClientId是什么?

ClientId是一个唯一的标识,用来区分每一个连接到代理(broker)的MQTT客户端、使代理(broker)跟踪客户端的当前状态。为保证唯一,ClientId应特定于每个客户端和代理。MQTT3.1.1允许在代理不需要维护任何状态的情况下使用空的ClientId。但是,这个连接必须将Clean Session标志设置为true,否则代理将拒绝连接。

MQTT CONNECT包中的CleanSession是什么?

CleanSession标记指示客户端是否要与代理(broker)建立持久会话。当CleanSession被设置为false(CleanSession = false)时,代理将存储客户端所有订阅以及订阅QoS级别为1或2的客户端的所有丢失消息。相反,当CleanSessioin被设置为true(CleanSession = true)时,代理(broker)不会为该客户端存储任何信息,并丢弃任何持久会话中的任何先前状态。

MQTT CONNECT包中的Username/Password是什么?

MQTT提供选项包括一个用户名和密码,用来客户端的认证和授权。但是,要注意的是,明文发送这些信息存在风险。为避免这个风险,我们强烈建议使用加密和哈希(比如通过TLS)来保护凭证。我们还建议在传输敏感数据时使用安全传输层。
另外,一些代理(broker)提供SSL证书认证,完全无需用户名和密码凭据。采取这些预防措施可确保你的MQTT通信保持安全并免受潜在的安全威胁。

MQTT CONNECT包中的Will Message是什么?

MQTT的遗嘱功能(LWT)包括遗嘱消息(will message),当一个客户端意外断开时通知其他客户端。客户端可以在CONNECT消息中将此消息指定为MQTT消息和主题。但客户端突然断开时,代理(broker)将代表客户端发送LWT消息。在后续章节中会对此进行详细的介绍。

MQTT CONNECT包中的Keep Alive是什么?

MQTT的keep alive功能允许客户端指定一个以秒为单位的时间间隔,当连接建立时,以此间隔和代理(broker)通信。这些时间间隔决定了代理(broker)和客户端能够通信的最长周期,而不用发送消息。为了保证连接活跃状态,客户端规律发送PING请求,代理(broker)返回一个PING响应。这种方面允许双方确认对方是否依旧可用。后续章节会对此进行详细的介绍。
当一个MQTT3.1.1客户端连接到代理(broker),keep alive时间间隔非常重要。

MQTT代理响应CONNACK消息

当代理(broker)收到CONNECT消息时,它有义务使用CONNACK消息进行响应。
image.png
CONNACK消息包含两个数据条目:

  • 当前会话标志
  • 连接返回状态码
CONNACK消息中的sessionPresent标志是什么?

sessionPresent标志通知客户端上一个会话是否在代理上仍然可用。如果客户端请求了一个clean会话,则该标志将始终为false,表示没有上一个会话。
但是,如果客户端请求恢复前一个会话,那么如果代理(broker)仍存储会话信息,则该标志将为true。该标志帮助客户端确定是否需要重新订阅主题,或者代理(broker)是否具有上一个会话的订阅。

CONNACK消息中的returnCode标志是什么?

returnCode是一个状态码,通知客户端连接尝试是否成功。这个状态码能够指示多种异常,比如不合法的凭据或不支持协议版本:

Return CodeReturn Code Response
0Connection accepted
1Connection refused, unacceptable protocol version
2Connection refused, identifier rejected
3Connection refused, server unavailable
4Connection refused, bad user name or password
5Connection refused, not authorized

这些状态码的更多详细解释,参见the MQTT specification.
注意连接的returnCode很重要,因为它可以帮助诊断连接问题。比如,如果returnCode指明认证失败,客户端可以使用正确的凭证重新连接。了解sessionPresent标志和连接returnCode对于成功的MQTT连接至关重要。

MQTT如何保持一个连接

如果你想知道MQTT如何在没有发送消息的情况下如何保持连接,或者如何确定连接何时丢失,不要担心,后续文章会更详细的介绍。

结论

总结下,对于任何有兴趣使用MQTT协议的人来说,理解MQTT客户端和代理(broker)以及连接建立的过程都非常重要。MQTT客户端库使向应用程序和设备添加MQTT支持变得容易,而无需从头实现协议。MQTT代理(broker)负责接收、过滤、发送消息到订阅的客户端,以及处理客户端认证和授权。
有了这些知识,就可以使用MQTT构建可扩展且高效的物联网系统。接下来的文章中,我们会讨论在MQTT中发布、订阅和取消订阅的更多高级内容。

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

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

相关文章

CSS——复合选择器、CSS特性、背景属性、显示模式

1、复合选择器 复合选择器:由两个或多个基础选择器,通过不同的方式组合而成。 作用:更准确、更高效的选择目标元素(标签) 1.1 后代选择器 后代选择器:选中某元素的后代元素 选择器写法:父选…

domain参数错误导致讯飞星火大模型:发生错误,错误码为:10404

问题 开通讯飞星火大模型api调用后,使用官方demo调用报错10404,最终发现是domain参数需要跟调用的版本保持一致,1.5,2,3版本分别传general,generalv2,generalv3,传错了还报错10404,感觉真没这必…

zabbix 监控

zabbit 监控 非常成熟的监控软件。 运维人员,尽快系统服务器的状态,网站的流量,服务进程的运行状态。 保证整个集群的工作正常。7*24 zabbix是什么: web界面提供的一种可视化监控服务软件。 分布式的方式系统监控以及网络监控…

Spring MVC数据绑定的几种方法(一)

这篇文章包含spring mvc的默认数据类型绑定和简单数据类型绑定。内容来自实验。 准备: (1)在IDEA环境中从archetye创建webapp类型的maven项目exp6。 (2)在src\main目录下创建并标注java源代码文件夹和resources资源文…

栈和队列的OJ题--13.用队列实现栈

13. 用队列实现栈 225. 用队列实现栈 - 力扣(LeetCode) /*解题思路: 此题可以用两个队列去实现一个栈,每次始终保持一个队列为空, 入栈操作相当于给非空队列进行入队操作 出栈操作相当于非空队列的队尾元素出队&…

Bean的加载控制

Bean的加载控制 文章目录 Bean的加载控制编程式注解式ConditionalOn*** 编程式 public class MyImportSelector implements ImportSelector {Overridepublic String[] selectImports(AnnotationMetadata annotationMetadata) {try {Class<?> clazz Class.forName("…

Qt OpenCV 学习(二):两个简单图片识别案例

1. 寻找匹配物体 1.1 mainwindow.h #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow> #include <opencv2/opencv.hpp>#include <QImage> #include <QString> #include <QPixmap>QT_BEGIN_NAMESPACE namespace Ui { class Main…

易宝OA ExecuteSqlForSingle SQL注入漏洞复现

0x01 产品简介 易宝OA系统是一种专门为企业和机构的日常办公工作提供服务的综合性软件平台,具有信息管理、 流程管理 、知识管理(档案和业务管理)、协同办公等多种功能。 0x02 漏洞概述 易宝OA ExecuteSqlForSingle、IsPartNumber接口处存在SQL注入漏洞,未经身份认证的攻…

openGauss学习笔记-140 openGauss 数据库运维-例行维护-例行维护表

文章目录 openGauss学习笔记-140 openGauss 数据库运维-例行维护-例行维护表140.1 相关概念140.2 操作步骤140.3 维护建议 openGauss学习笔记-140 openGauss 数据库运维-例行维护-例行维护表 为了保证数据库的有效运行&#xff0c;数据库必须在插入/删除操作后&#xff0c;基于…

【数据库】数据库元素的层次,树形结构的下的多粒度加锁,以及幻象的正确处理

数据库元素的层次 ​专栏内容&#xff1a; 手写数据库toadb 本专栏主要介绍如何从零开发&#xff0c;开发的步骤&#xff0c;以及开发过程中的涉及的原理&#xff0c;遇到的问题等&#xff0c;让大家能跟上并且可以一起开发&#xff0c;让每个需要的人成为参与者。 本专栏会定期…

ESP32-Web-Server编程综合项目1-结合 Web Server 实现 WiFi 配网和网页 OTA 更新

ESP32-Web-Server编程综合项目1-结合 Web Server 实现 WiFi 配网和网页 OTA 更新 概述 前述的内容多是一个个小功能的演示&#xff0c;本章节讲述一些实际项目中使用到的综合项目。 首先要讲述的案例是通过ESP32 上的 Web Server 实现对 ESP32 的 WiFi 配网和网页 OTA 更新功…

送女朋友一个猜数字小游戏,猜对了会显示爱心(给你心爱的他或她一个惊喜)

起因是我在学习C语言完成老师布置C语言写一个猜数字的作业&#xff0c;突发奇想&#xff0c;能不能在这个猜对了之后弹出一个不一样的页面&#xff0c;然后就试试看能不能实现。基本思路是这样的&#xff1a; 1&#xff1a;先写一个C语言的猜数字的小游戏&#xff0c;在我上个文…

DevEco Studio 调整开发工具中的字体大小与行高

我们打开编辑器 选择 左上角 File 下的 Settings 将左侧菜单栏 编辑 展开 我们在编辑下面 选择 Font 然后 如下图指向的两个位置 我们可以调整它的字体大小和行高 设置好之后 右下角 点击 Apply 应用 然后点击 OK即可 当然 你按着 Ctrl 然后鼠标滚动 也可以像浏览器那样 拉…

Google Colab 现已支持直接使用 transformers 库

Google Colab&#xff0c;全称 Colaboratory&#xff0c;是 Google Research 团队开发的一款产品。在 Colab 中&#xff0c;任何人都可以通过浏览器编写和执行任意 Python 代码。它尤其适合机器学习、数据分析和教育目的。从技术上来说&#xff0c;Colab 是一种托管式 Jupyter …

面试官:说说Vue中Proxy与Object.defineProperty的用法与区别

前言 面试时&#xff0c;我们说完Vue响应式原理&#xff0c;或者Vue2和Vue3的区别时&#xff0c;通常会引出Vue3使用了Proxy来优化响应式&#xff0c;而面试官会继续深挖&#xff1a;说说Proxy与Object.defineProperty的区别。 我们不能只说Proxy直接代理一个对象&#xff0c…

数据结构之二叉树及面试题讲解

&#x1f495;"从前种种譬如昨日死&#xff1b;从后种种譬如今日生"&#x1f495; 作者&#xff1a;Mylvzi 文章主要内容&#xff1a;数据结构之二叉树及面试题讲解 一.概念 1.树的定义 树是一种非线性的数据结构&#xff0c;是由n个结点组成的一种非线性集合&…

10. 哈希表

哈希表(hash table)&#xff0c;又称散列表&#xff0c;其通过建立键 key 与值 value 之间的映射&#xff0c;实现高效的元素查询。具体而言&#xff0c;我们向哈希表输入一个键 key &#xff0c;则可以在 \(O(1)\) 时间内获取对应的值 value 。 给定 n 个学生&#xff0c;每个…

OpenGL ES入门教程(三)之为平面桌子添加混合色

OpenGL ES入门教程&#xff08;三&#xff09;之为平面桌子添加渐变色 前言零、OpenGL ES实现混合色的原理一、修改绘制的桌子结构1. 三角形扇介绍2. 基于三角形扇结构绘制平面桌子 二、为每个顶点添加颜色属性三、修改着色器1. 顶点着色器2. 片段这色器 四、绘制具有混合颜色的…

Springboot依赖注入时重复初始化Bean的问题

前言 最近做项目&#xff0c;发现了springboot2.7.x在参数initiate的时候可以反复初始化&#xff0c;而且首次异常后&#xff0c;第二次成功居然也可以启动&#xff0c;通过查看源代码发现了问题根源&#xff0c;且在springboot高版本3.x&#xff0c;就出现了了Configuration的…

springmvc+mybatis+mysql8+idea+jqgrid前端

一、背景 主要是为了学习jqgrid前端技术,熟练一下前后端交互数据 二、效果图 访问地址:http://localhost:8080/cr/views/jqGridDemo.jsp 三、代码展示 控制层JqGridController.java @Controller @RequestMapping("/jqgrid") public class JqGridController {pr…