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 报文(取消订阅确认报文),如下图所示:

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

electron在VSCode和IDEA及webStrom等编辑器控制台打印日志乱码

window10环境下设置 1.打开Windows设置 2.打开时间和语言,选择语言菜单、如何点击管理语言设置 3.打开之后选择管理,选择更改系统区域设置,把Beta版:使用Unicode UTF-8提供全球语言支持 勾上,点击确定,…

后端学习(一)

添加数据库包: 数据库连接时 发生错误: 解决方式: SqlConnection conn new SqlConnection("serverlocalhost;databaseMyBBSDb;uidsa;pwd123456;Encryptfalse;") ;conn.Open();SqlCommand cmd new SqlCommand("SELECT * FROM…

Debug-017-elementUI-el-cascader组件首次选择选项不触发表单的自定义校验

前情提要: 今天维护一个表单校验的时候发现一件事情,就是在表单中使用了 el-cascader组件,希望根据接口返回数据去动态校验一下这里面的选项,符合逻辑就通过自定义的表单校验,不符合就在这一项的下面标红提示。做的时候…

OpenHarmony 入门——单元测试UnitTest快速入门

引言 OpenHarmony 的单元测试(UnitTest)是一个关键的软件开发过程,它确保代码的各个部分能够按预期工作,OpenHarmony的测试框架中提供了很多种的单元测试,今天简单介绍下UnitTest 类型的TDD测试。 OpenHarmony 的TDD …

群体优化算法---文化算法介绍,求解背包问题

介绍 文化算法(Cultural Algorithm, CA)是一种基于文化进化理论的优化算法,首次由Robert G. Reynolds在20世纪90年代提出。文化算法通过模拟人类社会中的文化进化过程,利用个体与群体的双重进化机制来解决优化问题。其基本思想是…

MGRE复习综合实验

R1与R5之间使用ppp的pap认证,R5为主认证方: R1 interface Serial4/0/0ip address 15.0.0.1 8link-protocol pppppp pap local-user huawei password cipher 123456 R5 aaalocal-user huawei password cipher 123456local-user huawei service-type…

海外媒体发稿-全媒体百科

全球知名媒体机构 在全球范围内,有许多知名的新闻机构负责报道世界各地的新闻事件。以下是一些国外常见的媒体机构: AP(美联社)合众国际社(UPI)AFP(法新社)EFE(埃菲通讯社)Europa …

JavaSE学习笔记第二弹——对象和多态(上)

目录 面向对象基础 面向对象程序设计的定义 类的基本结构 成员变量 成员方法 方法定义与使用 设计练习 方法重载 构造方法 静态变量和静态方法 String和StringBuilder 基本含义 区别 总结 今天我们继续来学习JavaSE,扩展和Java相关的知识,…

【软件分享】气象绘图软件Panoply

气象是大气中的物理现象,气象要素则是表明大气物理状况的要素,主要的气象要素有降水、风、气压、湿度等。为了研究气象要素在空间上的分布和运动状况,我们需要对气象要素进行空间上进行可视化,这个时候就需要气象领域的一些的绘图…

FastReport 指定sql,修改数据源 ( 非DataSet修改 )

FastReport 指定sql,修改数据源,非DataSet修改 介绍报告文件: codetest.frx 文件核心代码:(扩展)小结一下: 介绍 在FastReport中,经常会遇到需要给 sql 加条件的情况。 &#xff0…

Open3D KDtree的建立与使用

目录 一、概述 1.1kd树原理 1.2kd树搜索原理 1.3kd树构建示例 二、常见的领域搜索方式 2.1K近邻搜索(K-Nearest Neighbors, KNN Search) 2.2半径搜索(Radius Search) 2.3混合搜索(Hybrid Search) …

进程 VS 线程(javaEE篇)

🍁 个人主页:爱编程的Tom💫 本篇博文收录专栏:JavaEE初阶👉 目前其它专栏:c系列小游戏 c语言系列--万物的开始_ 等 🎉 欢迎 👍点赞✍评论⭐收藏💖三连支…

shell脚本编程的练习

字符测试方法: 双目测试 比较两个字符串: :等于,等值比较 !:不等 单目测试: -n $stringVar:字符串是否为空,不空为真,空则为假 -z $stringVar:字符串是否为空,空则为…

xxl-job集成SpringBoot

安装xxl-job客户端一般有很多方式,我这里给大家提供两种安装方式,包含里面的各项配置等等。 前期需要准备好MySQL数据库。复制SQL到数据库里面。 # # XXL-JOB v2.4.2-SNAPSHOT # Copyright (c) 2015-present, xuxueli.CREATE database if NOT EXISTS x…

终于找到了免费的C盘清理软件(极智C盘清理)

搜了很久,终于让我找到了一款 完全免费的C盘清理软件(极智C盘清理)。 点击前往官网免费使用极智C盘清理软件: C盘清理 用户好评 完全免费的极智C盘清理 用极智C盘清理清理了下系统的临时文件、缓存等无用数据文件,C盘终…

JavaDS —— 顺序表ArrayList

顺序表 顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。在物理和逻辑上都是连续的。 模拟实现 下面是我们要自己模拟实现的方法: 首先我们要创建一个顺序表,顺序表…

00 Debian字符界面如何支持中文

作者:网络傅老师 特别提示:未经作者允许,不得转载任何内容。违者必究! Debian字符界面如何支持中文 《傅老师Debian知识库系列之00》——原创 前言 傅老师Debian知识库特点: 1、拆解Debian实用技能; 2、…

Python--并发编程--协程

概念 协程是轻量级的线程,它是程序员管理的并发机制,使得在一个线程中程序可以在多个函数之间交替运行。 Python中主要通过asyncio模块实现协程。 协程函数 用async修饰的函数 import asyncio# func为协程函数 async def func():await asyncio.slee…

博美犬插画:成都亚恒丰创教育科技有限公司

​博美犬插画:萌动心灵的细腻笔触 在浩瀚的艺术海洋中,有一种艺术形式总能以它独有的温柔与细腻,触动人心最柔软的部分——那便是插画。而当插画遇上博美犬这一萌宠界的明星,便诞生了一幅幅令人爱不释手的作品,成都亚…

CLIP编码器调用时刚开始正常,然后输出全部变为NaN

碰到了这个问题:输入是正常的,输出全是NaN 网上办法不多,找了半天终于看到问题所在,但是没有说在哪里改的,故记录一下。 改一下模型精度就正常了,默认的是fp16,改为fp32即可 具体步骤如下&…