imx6ull/linux应用编程学习(14) MQTT基础知识

什么是mqtt?

        与HTTP 协议一样, MQTT 协议也是应用层协议工作在 TCP/IP 四层模型中的最上层(应用层)构建于 TCP/IP协议上。 MQTT 最大优点在于,可以以极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务。作为一种低开销、低带宽占用的即时通讯协议,使其在物联网、小型设备、移动应用等方面有较广泛的应用

        MQTT 协议是为工作在低带宽、不可靠网络的远程传感器和控制设备之间的通讯而设计的协议,它具有以下主要的几项特性:

①、 使用发布/订阅消息模式,提供一对多的消息发布,解除应用程序耦合。

②、基于 TCP/IP 提供网络连接。

        主流的 MQTT 是基于 TCP 连接进行数据推送的,但是同样也有基于 UDP 的版本,叫做 MQTT-SN。这两种版本由于基于不同的连接方式,优缺点自然也就各有不同了。

③、支持 QoS 服务质量等级。

根据消息的重要性不同设置不同的服务质量等级。

④、 小型传输, 开销很小,协议交换最小化,以降低网络流量。

        这就是为什么在介绍里说它非常适合"在物联网领域,传感器与服务器的通信,信息的收集",要知道嵌入式设备的运算能力和带宽都相对薄弱,使用这种协议来传递消息再适合不过了, 在手机移动应用方面, MQTT 是一种不错的 Android 消息推送方案。

⑤、使用 will 遗嘱机制来通知客户端异常断线。

⑥、基于主题发布/订阅消息,对负载内容屏蔽的消息传输。

⑦、支持心跳机制。

MQTT 通信基本原理

服务端和客户端


        MQTT 是一种基于客户端-服务端架构的消息传输协议,所以在 MQTT 协议通信中,有两个最为重要的角色,它们便是服务端和客户端

MQTT 主题

        客户端想要从服务器获取信息,首先需要订阅信息,"主题”在 MQTT 通信中是一个非常重要的概念,客户端发布信息以及订阅信息都是围绕“主题”来进行的。

        客户端发布消息时需要为消息指定一个“主题”, 表示将消息发布到该主题;而对于订阅消息的客户端来说,可通过订阅“主题” 来订阅消息,这样当其它客户端或自己(当前客户端)向该主题发布消息时, MQTT 服务端就会将该主题的信息发送给该主题的订阅者(客户端)。

        在以上图示中一共有三个 MQTT 客户端, 它们分别是开发板、 手机和电脑。 MQTT 服务端在管理 MQTT通信时使用了“主题”来对信息进行管理。比如上图所示,假设我们需要利用手机和电脑获取开发板在运行过程中 SoC 芯片的温度,那么首先电脑和手机这两个客户端需要向 MQTT 服务器订阅主题“芯片温度” ;接下来,当开发板客户端向服务端的“芯片温度”主题发布信息(假设信息的内容就是当前的温度值) 后服务端就会首先检查都有哪些客户端订阅了“芯片温度”这一主题的信息,而当它发现订阅了该主题的客户端有一个手机和一个电脑,于是服务端就会将刚刚收到的“芯片温度”信息转发给订阅了该主题的手机和电脑客户端。

        以上实例中, 开发板是“芯片温度”主题的发布者,而手机和电脑则是该主题的订阅者。

值得注意的是, MQTT 客户端在通信时,角色往往不是单一的, 一个客户端既可以作为信息发布者也可以同时作为信息订阅者。如下图所示:

        图中的所有客户端都是围绕“LED 控制”这一主题进行通信。此时,对于“LED 控制”这一主题来说,手机和电脑客户端成为了 MQTT 信息的发布者而开发板则成为了 MQTT 信息的订阅者(接收者)。

MQTT 发布/订阅特性
 

客户端相互独立
        MQTT 客户端是一个个独立的个体, 它们无需了解彼此的存在,依然可以实现信息交流。

空间上分离

        MQTT 客户端以及 MQTT 服务端它们在通信时是处于同一个通信网络中的, 这个网络可以是互联网或者局域网; 只要客户端联网,无论他们远在天边还是近在眼前,都可以实现彼此间的通讯交流;其实网络通信本就是如此,所以并不是 MQTT 通信所特有的。

时间上可异步
        MQTT 客户端在发送和接收信息时无需同步。这一特点对物联网设备尤为重要

连接 MQTT 服务端

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

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

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

        总结一句话就是:客户端先向服务端发送 CONNECT报文,服务端收到连接请求后,再向待连接的客户端发送 CONNACK 报文

CONNECT 报文
 

        如果此 CONNECT 报文的格式或内容不符合 MQTT 规范,则服务器会拒绝客户端的连接请求。

        CONNECT 报文包含的信息如下图所示:


        所谓报文就是一个数据包, 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 来区分不同的客户端。

        keepAlive--心跳时间间隔

        有些客户端并不经常发送消息给服务端, 对于这种客户端, MQTT 协议使用了类似心跳检测的方法来判断客户端是否在线。客户端在没有向服务端发送信息时(空闲时) ,可以定时向服务端发送一个心跳数据包,这个心跳包也被称作心跳请求, 心跳请求的作用正是用于告知服务端,当前客户端依然在线。
        譬如 keepAlive=60,表示告诉服务端,客户端将会每隔 60 秒左右向服务端发送心跳包。


        cleanSession--清除会话

        这是一个布尔值, cleanSession 标志可用于控制客户端与服务端在连接和断开连接时的行为,我们举个例子来进行说明, QQ、微信这些聊天软件大家都用过,假设当前你的 QQ 账号没有登录或者说当前处于离线状态,与服务器断开了连接; 而在离线期间,你的 QQ 好友给你发了几条信息; 由于当前你的 QQ 处于离线状态,自然是接收不到好友发送过来的信息,但是, 当你的 QQ 恢复连接状态时,立马会接收到好友在离线期间所发给你的信息

        如果连接服务端时 cleanSession=0, 当 MQTT 客户端由离线(与服务端断开连接)再次上线时,离线期间发给客户端的所有 QoS>0 的消息仍然可以接收到;如果连接服务端时 cleanSession=1, 当 MQTT 客户端由离线(与服务端断开连接)再次上线时,离线期间发
给客户端的所有消息一律接收不到。
        说白了,想接收离线消息, 客户端连接服务端时就必须使用 cleanSession=0;除了这个作用之外,如果cleanSession=0,则 MQTT 服务端会在客户端断开连接之后“记住” MQTT 客户端在线期间所订阅的所有“主题”;也就是说,服务端会保存、存储客户端所订阅的主题。
        如果 cleanSession=1,客户端既无法接收到离线消息、服务端也不会记住该客户端所订阅的主题, 服务端不会保存客户端的会话状态, 每次连接都是一次新的会话

下面再看看 MQTT 服务端接收到客户端发来的连接请求后所回复的 CONNACK 报文详细内容


CONNACK 报文


returnCode--连接返回码


        当服务端收到了客户端的连接请求后,会向客户端发送 returnCode(连接返回码), 用来说明连接情况。如果客户端与服务端成功连接,则返回数字“0”。如果未能成功连接,返回码将会是一个非零的数字,具体这个数字的含义,请见下表


       sessionPresent


        在 cleanSession=0 的情况下, 当客户端连接到服务器之后, 可通过 CONNACK 报文中返回的sessionPresent 来查询服务端是否为客户端保存了会话状态(客户端上一次连接时的会话状态信息) , 如果服务端已为客户端保存了上一次连接时的会话状态,则 sessionPresent=1,如果没有保存会话状态,则sessionPresent=0。

        如果 cleanSession=1, 在这种情况下,客户端是不需要服务端保存会话状态的, 那么服务端发送的确认连接 CONNACK 报文中, sessionPresent 肯定是 false(sessionPresent=0) ,也就是说,服务端没有保存客户端的会话状态信息。

        简言之, CONNACK 报文的 sessionPresent 与 CONNECT 报文的 cleanSession 相互配合。其作用是客户端发送连接请求时,服务端告知客户端有没有保存会话状态。这个被服务端保存的会话状态是来自于上一次客户端连接时,譬如离线消息以及上一次连接时客户端所订阅的主题。

断开连接
 

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

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

PUBLISH– 发布消息
        当客户端连接到服务端之后,就可以向服务端发布消息了, 每条发布的消息必须指定一个“主题”,表示向某主题发布消息,MQTT 客户端向服务端发布消息其实就是向服务端发送一个 PUBLISH 报文, 服务端收到客户端发送过来的 PUBLISH 报文之后,会向发送发回复一个报

SUBSCRIBE--订阅主题
        客户端要想订阅主题,首先要向服务端发送主题订阅请求。客户端是通过向服务端发送 SUBSCRIBE 报文来实现这一请求的。该报文包含有一系列“订阅主题名”。请留意,一个 SUBSCRIBE 报文可以包含有单个或者多个订阅主题名。也就是说,一个 SUBSCRIBE 报文可以用于订阅一个或者多个主题。

        另外每一个 SUBSCRIBE 报文还包含有“报文标识符”。报文标识符可用于对 MQTT 报文进行标识。不同的 MQTT 报文所拥有的标识符不同。 MQTT 设备可以通过该标识符对 MQTT 报文进行甄别和管理。当客户端向服务端发送 SUBSCRIBE 报文,服务端接收到 SUBSCRIBE 报文之后会向客户端回复一个SUBACK 报文(订阅确认报文),如下图所示:

UNSUBSCRIBE--取消订阅主题
 

        客户端订阅了某一主题之后,可以随时取消订阅, MQTT 协议提供了这样的操作。

客户端通过向服务端发送一个 UNSUBSCRIBE 报文来取消订阅主题,当服务端接收到 UNSUBSCRIBE报文后,会向发送发回复一个 UNSUBACK 报文(取消订阅确认报文),如下图所示:

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

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

相关文章

网络资源模板--Android Studio 外卖点餐App

目录 一、项目演示 二、项目测试环境 三、项目详情 四、完整的项目源码 原创外卖点餐:基于Android studio 实现外卖(点)订餐系统 非原创奶茶点餐:网络资源模板--基于 Android Studio 实现的奶茶点餐App报告 一、项目演示 网络资源模板--基于Android …

在AvaotaA1全志T527开发板上使用AvaotaOS 部署 Docker 服务

Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows操作系统的机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。 准备…

信息技术课上的纪律秘诀:营造有序学习环境

信息技术课是学生们探索数字世界的乐园,但同时也是课堂纪律管理的挑战场。电脑、网络、游戏等元素可能分散学生的注意力,影响学习效果。本文将分享一些有效的策略,帮助教师在信息技术课上维持课堂纪律,确保教学活动顺利进行。 制…

几何建模基础-样条曲线和样条曲面介绍

1.概念介绍 1.1 样条曲线的来源 样条的英语单词spline来源于可变形的样条工具,那是一种在造船和工程制图时用来画出光滑形状的工具:富有弹性的均匀细木条/金属条/有机玻璃条,它围绕着按指定位置放置的重物或者压铁做弹性弯曲,以…

基于LangChain的RAG开发教程(二)

v1.0官方文档:https://python.langchain.com/v0.1/docs/get_started/introduction/ 最新文档:https://python.langchain.com/v0.2/docs/introduction/ LangChain是一个能够利用大语言模型(LLM,Large Language Model)能…

植物大战僵尸融合嫁接版 MAC 版本下载安装详细教程

继植物大战僵尸杂交版火了之后,PVZ改版可谓是百花齐放,最近又有一个非常好玩的模式被开发出来了,他们称为《植物大战僵尸融合嫁接版》 该版本并没有对植物卡牌做改动,而是可以将任意两种植物叠放到一起进行融合,产生新…

思路打开!腾讯造了10亿个角色,驱动数据合成!7B模型效果打爆了

世界由形形色色的角色构成,每个角色都拥有独特的知识、经验、兴趣、个性和职业,他们共同制造了丰富多元的知识与文化。 所谓术业有专攻,比如AI科学家专注于构建LLMs,医务工作者们共建庞大的医学知识库,数学家们则偏爱数学公式与定…

数据分析与挖掘实战案例-电商产品评论数据情感分析

数据分析与挖掘实战案例-电商产品评论数据情感分析 文章目录 数据分析与挖掘实战案例-电商产品评论数据情感分析1. 背景与挖掘目标2. 分析方法与过程2.1 评论预处理1. 评论去重2. 数据清洗 2.2 评论分词1. 分词、词性标注、去除停用词2. 提取含名词的评论3. 绘制词云查看分词效…

昇思25天学习打卡营第12天 | LLM原理和实践:MindNLP ChatGLM-6B StreamChat

1. MindNLP ChatGLM-6B StreamChat 本案例基于MindNLP和ChatGLM-6B实现一个聊天应用。 ChatGLM-6B应该是国内第一个发布的可以在消费级显卡上进行推理部署的国产开源大模型,2023年3月就发布了。我在23年6月份的时候就在自己的笔记本电脑上部署测试过,当…

UI自动化测试框架:PO 模式+数据驱动(超详细)

1. PO 设计模式简介 什么是 PO 模式? PO(PageObject)设计模式将某个页面的所有元素对象定位和对元素对象的操作封装成一个 Page 类,并以页面为单位来写测试用例,实现页面对象和测试用例的分离。 PO 模式的设计思想与…

Python学习中进行条件判断(if, else, elif)

条件判断是编程中必不可少的一部分,它让程序可以根据不同的条件执行不同的代码块。在Python中,主要使用if、elif和else语句来实现条件判断。 基本语法 在Python中,条件判断的基本语法如下: if condition:# 当condition为True时…

NCCL 中的一些辅助debug 知识点

1&#xff0c;调试nccl 启动kernel的方法 ncclLaunchKernel cuLaunchKernelEx ncclStrongStreamLaunchKernel cudaLaunchKernel ncclLaunchOneRank cudaLaunchKernel 在 nccl lib 中&#xff0c;不存在使用<<<grid, block,,>>> 这种类似方式启…

算法题型归类整理及同类题型解法思路总结(持续更新)

1、最优路线 通用思路 1、递归 #案例1-最优路测路线 题目描述 评估一个网络的信号质量&#xff0c;其中一个做法是将网络划分为栅格&#xff0c;然后对每个栅格的信号质量计算。 路测的时候&#xff0c;希望选择一条信号最好的路线&#xff08;彼此相连的栅格集合&#x…

12种增强Python代码的函数式编程技术

前言 什么是函数式编程&#xff1f; 一句话总结&#xff1a;函数式编程(functional programming)是一种编程范式&#xff0c;之外还有面向对象&#xff08;OOP&#xff09;、面向过程、逻辑式编程等。 函数式编程是一种高度抽象的编程范式&#xff0c;它倡导使用纯函数&#x…

Docker-11☆ Docker Compose部署RuoYi-Cloud

一、环境准备 1.安装Docker 附:Docker-02-01☆ Docker在线下载安装与配置(linux) 2.安装Docker Compose 附:Docker-10☆ Docker Compose 二、源码下载 若依官网:RuoYi 若依官方网站 鼠标放到"源码地址"上,点击"RuoYi-Cloud 微服务版"。 跳转至G…

深入理解计算机系统 CSAPP 家庭作业8.22

书本知识够你写出答案,但是如果你想验证你写的答案,就要一些额外的东西.这本书很多题目都是如此 /** mysystem.c*/ #include <stdio.h> #include "csapp.h"int mysystem(char* command) {pid_t pid;int status;if ((pid Fork()) 0) {/*这里是关键用子程序去…

新加坡工作和生活指北:工作篇

文章首发于公众号&#xff1a;Keegan小钢 一年多以前&#xff08;2022 年 8 月初&#xff09;&#xff0c;那时我过来新加坡才 4 个多月&#xff0c;就写了篇文章分享了当时在新加坡的生活和工作体验。文章得到的反响不错&#xff0c;但也反馈出了一些新的问题&#xff0c;比如…

预训练对齐:数学理论到工程实践的桥梁

在人工智能和机器学习领域&#xff0c;预训练模型的对齐是一个至关重要的概念。本篇博客源自听了一场黄民烈老师关于大模型对齐的分享&#xff0c;整理内容如下&#xff0c;供大家参考。 数学理论中的预训练对齐 数学理论上&#xff0c;预训练对齐是什么&#xff1f; 序列…

Keepalived+HAProxy 集群及虚IP切换实践

1、软件介绍 ①Keepalived keepalive是一个用c语言编写的路由软件&#xff0c;这个项目的主要目标是为Linux系统和基于Linux的基础设施提供简单而健壮的负载平衡和高可用性设施。负载均衡框架依赖于众所周知且广泛使用的Linux Virtual Server (IPVS)内核模块提供第4层负载均衡…

srs直播内网拉流带宽飙升问题记录

问题背景 srs部署在云服务器上&#xff0c;32核cpu&#xff0c;64G内存&#xff0c;带宽300M. 客户端从srs拉流&#xff0c;发现外网客户端拉流&#xff0c;cpu和带宽都正常。然而内网客户端拉流&#xff0c;拉流人数超过5人以上&#xff0c;带宽就会迅速飙升。 排查 用srs…