IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> MQTT物联网 -> 正文阅读

[嵌入式]MQTT物联网

????????物联网通讯是物联网的一个核心内容,目前物联网的通讯协议并没有一个统一的标准,比较常见的有MQTT、 CoAP DDS XMPP 等,其中, MQTT (消息队列遥测传输协议)是应用最广泛的标准之一。

一.MQTT简介

? ? ? ? 什么是MQTT?先从名字来看,Message Queuing Telemetry Transport:消息队列遥测传输。《MQTT 协议规范中文版》中的解释是:

MQTT 是一种基于客户端服务端架构的发布 / 订阅模式的消息传输协议。它的设计思想是轻巧、开放、 简单、规范,易于实现。这些特点使得它对很多场景来说都是很好的选择,特别是对于受限的环境如机器与 机器的通信( M2M )以及物联网环境( IoT )。

?????????MQTT协议是应用层协议,其最大的优点是以极少的代码和有限的带宽(低开销、低带宽),为连接远程设备提供实时可靠的消息服务。

二.MQTT主要特性

使用发布/订阅消息模式,提供一对多的消息发布。

②基于TCP/IP提供网络连接(也有UDP版本)。

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

④开销小,带宽占用小。

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

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

⑦支持心跳机制。

三.MQTT协议

MQTT Version 3.1.1 协议资料

1.MQTT 通信基本原理

????????MQTT是一种基于 客户端 - 服务端 架构的消息传输协议,所以 最重要的角色便是服务端 客户端
? ? ? ? 服务端
? ? ? ? 在MQTT中,服务端一般是服务器,它主要负责接收客户端消息、发布消息到客户端,以及管理客户端,保证客户端之间的通信消息正确传输和接收。
? ? ? ? 客户端
? ? ? ??MQTT 客户端可以向服务端发布信息,也可以从服务端收取信息;把客户端发送信息的行为称为 “发布”信息。而客户端要想从服务端收取信息,则首先要向服务端“订阅主题”信息。“订阅主题”信息这一操作就是告诉服务端,以后这个主题下的消息更新时请发送给我。
? ? ? ? MQTT主题
? ? ? ? “主题”在 MQTT 通信中是一个非常重要的概念,客户端发布信息以及订阅信息都是围绕“主题”来进行的,并且 MQTT 服务端在管理 MQTT 信息时,也是使用“主题”来控制的。
? ? ? ??客户端发布消息时需要为消息指定一个“主题”,表示将消息发布到该主题;而对于订阅消息的客户端来说,可通过订阅“主题”来订阅消息,这样当其它客户端或自己向该主题发布消息时,MQTT 服务端就会将该主题的信息发送给订阅了该主题的客户端。
? ? ? ? 如图为一个简单地MQTT实例,在这个实例中有三个客户端以及一个服务器,三个客户端都订阅了“芯片温度”这个主题,当开发板向这个主题发送消息时。消息会送到服务器,服务器对消息进行分析处理后向订阅了该主题的其他两个客户端发送开发板发送的芯片温度消息。这样我们就能从手机或者电脑上获得芯片温度的消息,同理我们还能做很多很多事情。

? ? ? ? 在MQTT中客户端既可以作为消息的发布者,也可以作为消息的订阅者。在下图中,手机和电脑客户端成为了 MQTT 信息的发布者而开发板则成为了 MQTT 信息的订阅者。

????????MQTT 发布 / 订阅特性
? ? ? ? 从上述实例中可以看出,MQTT 通信的核心枢纽是 MQTT服务端它负责将 MQTT客户端发送来的 信息传递给 MQTT 客户端,还负责管理 MQTT 客户端,以确保客户端之间的通讯顺畅,保证 MQTT 信息得以正确接收和准确投递。
? ? ? ? 因为服务器端的存在,MQTT的发布和订阅具有以下分布/订阅特性:
????????客户端 相互独立:
????????MQTT 客户端之间是相互独立的,它们则用做自己想做的事,不用管其他客户端是谁,就可以实现信息交流。
????????空间上 分离:
网络通信嘛。
????????时间上 异步:
????????MQTT 客户端在发送和接收信息时无需同步,因为物联网设备在运行过程中发生意外掉线是非常正常的情况。假如因为某种原因开发板断开与 MQTT 服务端的连接。假设此时我们的手机客户端向开发板客户端所订阅的“LED 控制”主题发布了信息,而开发板恰恰不在线,这时,MQTT 服务端可以将“LED 控制”主题的新信息保存,待开发板客户端再次上线后,服务端再将“LED 控制”信息推送给开发板。所以这就必然导致了,手机发送信息与开发板接收信息在时间上是异步的。

2.MQTT连接服务端

? ? ? ? 在MQTT中想要实现客户端的通信,必须借助服务端,所以必须先和服务器建立连接。其具体连接步骤分为以下两步:

①客户端向服务端发送一个请求连接的CONNECT报文,也就是发送了一个CONNECT数据包;

MQTT服务端收到连接请求后,会向客户端发送连接确认的CONNACK报文,也就是 CONNACK 数据包。

? ? ? ? CONNECT报文:

? ? ? ? 客户端发的的CINNECT报文必须符合规范,否则服务端会拒绝连接,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 必须是独立的,如果两个MQTT客户端使用相同clientId 标识,服务端会把它们当成同一个客户端来处理。通常 clientId 是由一串字符所构成的

????????keepAlive--心跳时间间隔

????????MQTT协议使用了类似心跳检测的方法来判断客户端是否在线。客户端可以定时向服务端发送一个心跳数据包来告知服务端,当前客户端在线,服务端在收到客户端的心跳数据包后,会回复一条消息,这条回复消息被称作心跳响应。keepAlive的单位为秒。

????????cleanSession--清除会话

????????这是一个布尔值,cleanSession 标志可用于控制客户端与服务端在连接和断开连接时的行为。连接服务端时 cleanSession=0,当 MQTT 客户端由离线(与服务端断开连接)再次上线时,离线期间发给客户端的所有 QoS>0 的消息仍然可以接收到; 如果连接服务端时cleanSession=1,当 MQTT 客户端由离线(与服务端断开连接)再次上线时,离线期间发给客户端的所有消息一律接收不到,并且服务器端也不会记住客户端在线期间订阅的主题。

? ? ? ? 也就是说:cleanSession 设置为 1,表示此次连接将创建一个新的临时会话,在客户端断开后,这个会话会自动销毁。而 cleanSession 设置为 0,表示创建一个持久性会话,在客户端断开连接时,会话仍然保持并保存离线消息,直到会话超时注销,并且会记住该客户端订阅的主题。

????????CONNACK 报文:

? ? ? ? ?CONNACK报文主要内容如下:

?returnCode--连接返回码

????????当服务端收到了客户端的连接请求后,会向客户端发送 returnCode(连接返回码),用来说明连接情况。 如果成功连接,则返回“0”。如果失败,则返回一个非零的数字:

返回码说明
0
连接成功
1
连接被服务端拒绝,原因是不支持客户端的 MQTT 协议版本
2
连接被服务端拒绝,原因是不支持客户端标识符的编码。可能造成此原因的
是客户端标识符编码是 UTF-8 ,但是服务端不允许使用此编码。
3
连接被服务端拒绝,原因是服务端不可用。即,网络连接已经建立,但 MQTT
服务不可用。
4
连接被服务端拒绝,原因是用户名或密码无效。
5
连接被服务端拒绝,原因是客户端未被授权连接到此服务端。
6-255
保留备用
????????sessionPresent
????????
????????在 cleanSession=0 的情况下,当客户端连接到服务器之后,可通过 CONNACK 报文中返回的 sessionPresent 来查询服务端是否为客户端保存了会话状态(客户端上一次连接时的会话状态信息),如果服务端已为客户端保存了上一次连接时的会话状态,则 sessionPresent=1 ,如果没有保存会话状态,则sessionPresent=0。

3.MQTT断开连接

????????如果客户端想要断开与服务端的连接,客户端可以主动向服务端发送一个DISCONNECT报文来断开与服务端的连接。

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

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

????????PUBLISH–发布消息

????????每条发布的消息必须指定一个“主题”,表示向该主题发布消息,发布消息就是向服务端发送一PUBLISH 报文,服务端收到客户端发送过来的 PUBLISH 报文之后,会向发送发回复一个报文。根据 QoS 的不同,回复的报文类型和过程会有所区别。

? ? ? ? PUBLISH报文的主要内容为:

????????packetId--报文标识符

????????报文标识符可用于对 MQTT 报文进行标识,不同的 MQTT 报文所拥有的标识符不同。MQTT 设备可以通过该标识符对 MQTT 报文进行甄别和管理。报文标识符的内容与 QoS 级别有很大关系。

????????topicName--主题名字

?????????这个就是发布消息时对应的主题的名字,一般是一个字符串。

????????payload--有效载荷

????????有效载荷就是我们希望通过 MQTT 所发送的实际内容,可以是字符串文本,也可以是图像。

????????qos--服务质量等级

????????QoS(Quality of Service)表示 MQTT 消息的服务质量等级。QoS 有三个级别:01 2QoS 决定MQTT 通信有什么样的服务保证。

????????retain--保留标志

????????在默认情况下,当客户端订阅了某一主题后,并不会马上接收到该主题的信息。因为客户端订阅该主题之后,并没有其它客户端向该主题发布消息;但是在有些情况下,我们需要客户端在订阅了某一主题后马上接收到一条该主题的信息。这时候就需要用到保留标志这一信息。

????????dup--重发标志

????????dup 标志指示此消息是否是重复发送的消息。当 MQTT 报文的接收方没有及时向报文发送发回复确认收到报文时,发送方会以为对方没有收到信息,会再次重复发送 MQTT 报文在重复发送 MQTT 报文时,发送方会将此消息的dup设置为 true。请注意,重发标志只在 QoS 级别大于 0 时使用。

????????SUBSCRIBE--订阅主题

????????当客户端连接到服务端后,除了可以发布消息,也可以接收消息,但如果需要接收到消息,需要先订阅相关主题。

????????客户端是通过向服务端发送 SUBSCRIBE 报文来实现这一请求的。一个 SUBSCRIBE 报文可以用于订阅一个或者多个主题,并且客户端在订阅主题时也可以明确 QoS,服务端会根据 SUBSCRIBE 中的 QoS 来提供相应的服务保证。当客户端向服务端发送 SUBSCRIBE 报文,服务端接收到 SUBSCRIBE 报文之后会向客户端回复一个 SUBACK 报文(订阅确认报文)。SUBACK 报文包含有“订阅返回码”和“报文标识符”这两个信息。

????????returnCode--订阅返回码

返回码说明
0x00
订阅成功 --QoS0
0x01
订阅成功 --QoS1
0x02
订阅成功 --QoS2
0x80
订阅失败
????????UNSUBSCRIBE--取消订阅主题
????????
????????客户端通过向服务端发送一个 UNSUBSCRIBE 报文来取消订阅主题,当服务端接收到 UNSUBSCRIBE 报文后,会向发送发回复一个 UNSUBACK 报文(取消订阅确认报文)。
UNSUBSCRIBE 报文包含两个重要信息,第一个是取消订阅的主题名称,一个 UNSUBSCRIBE 报文可以包含多个取消订阅的主题名称。另外,UNSUBSCRIBE 报文也包含“报文标识符”, MQTT 设备可以通过该标识符对报文进行管理。 当服务端接收到 UNSUBSCRIBE 报文后,会向客户端发送取消订阅确认报文 UNSUBACK 报文。 该报文含有客户端所发送的“取消订阅报文标识符”。

5.主题

1)主题名

主题的基本形式就是一个字符串:区分大小写,可以使用空格(不建议使用),不能有中文。

2)主题分级

????????MQTT 协议为了更好的对主题进行管理和分类,支持主题分级,对主题进行分级处理,各个级别之间使用" / "符号 进行分隔(不要以/开头)。如下所示:
"home/sensor/led/brightness"

3)主题通配符?

?????????单级通配符:+

????????单级通配符可以匹配任意一个主题级别:

"home/sensor/+/status"

????????当客户端订阅了上述主题之后,将会收到以下主题的信息内容:

"home/sensor/led/status"
"home/sensor/key/status"
"home/sensor/beeper/status"
......

????????多级通配符:#

????????多级通配符自然是可以匹配任意数量个主题级别:

"home/sensor/#"

????????当客户端订阅了上面这个主题之后,便可以收到如下注意的信息:

"home/sensor/led"
"home/sensor/key"
"home/sensor/beeper"
"home/sensor/led/status"
"home/sensor/led/brightness"
"home/sensor/key/status"
"home/sensor/beeper/status"
......
????????以$ 开头的主题
???????? $ 号开头的主题是 MQTT 服务端系统保留的特殊主题,客户端不可随意订阅或向其发布信息;

6.QoS

????????QoS(Quality of Service)也就是服务质量,一个物联网通信中有些信息非常重要,我 们需要确保这类重要信息可以准确无误的发送和接收,而有些信息则相对不那么重要,这类信息如果在传输中丢失不会影响系统的运行;QoS就用来定义消息的重要性,并提供相对应的服务。

????????MQTT 设计了一套保证消息稳定传输的机制,包括消息应答、存储和重传。在这套机制下,提供了三种不同级别的 QoSQuality of Service),也就是 MQTT 协议有三种服务质量等级:????????

????????QoS = 0:最多发一次:

? ? ? ??0 是服务质量 QoS 的最低级别。当 QoS 0 级时,MQTT 协议并不保证所有信息都能得以传输。也就是说,QoS=0 的情况下,MQTT 服务端和客户端不会对消息传输是否成功进行确认和检查。消息能否成功传输全看网络环境是否稳定。也就是说发送一次之后就不管了,最多一次,不管发送是否失败!发送端一旦发送完消息后,就完成任务了,发送端不会检查发出的消息能否被正确接收到。在网络环境稳定的情况下,信息传输一般是不会出现问题的。这完全依赖于 TCP 重传机制,如果网络 不好,TCP 的重传也不是 100%可靠,加上 MQTT 是发送方发出去的消息是依赖代理服务器完成转发的,所以消息最多一次。

????????QoS = 1:最少发一次:

????????当 QoS 级别为 1 时,发送端在消息发送完成后,会检查接收端是否已经成功接收到了消息。发送端向接收端发送 PUBLISH 报文,当接收端收到 PUBLISH 报文后会向发送端回复PUBACK报 文,如果发送端收到 PUBACK 报文,那么它就知道消息已经被接收端成功接收! 假如过了一段时间后,发送端没有收到 PUBACK 报文,那么发送端会再次发送消息(发送PUBLISH 报文),然后再次等待接收端的 PUBACK 确认报文。因此,当 QoS=1 时,发送端在一定时间内没有收到接 收端的 PUBACK 确认报文,会重复发送同一条消息。 所以 QoS=1 时,每一条消息就至少会传输一次,但也可能会重复传输多次。当发送端重复发送一条消 息时,会将 PUBLISH 报文中的 dup 标志设置为 true。这就是为了告诉接收端,此消息 为重复发送的消息,那么我们的 MQTT 客户端在接收到消息之后,可以去判断 dup 标志以确定此消息是否 为重复消息,应用程序应该对此作出相应的处理。

????????QoS = 2:保证收一次:

????????MQTT 服务质量最高级是 2 级,即 QoS=2。当 MQTT 服务质量为 2 级时,MQTT 协议可以确保接收端只接收一次消息(注意是只接收到一次,在 QoS=1 的情况下,接收端接收到消息的次数可能不止一次:>=1

①、首先发送端向接收端发送 PUBLISH 报文;

②、接收端接收到 PUBLISH 报文后,向发送端回复一个 PUBREC 报文(官方称其为 -- 发布收到);
③、发送端接收到 PUBREC 报文后,会再次向接收端发送 PUBREL 报文(官方称其为 -- 发布释放);
④、接收端接收到 PUBREL 报文后,会再次向发送端回复一个 PUBCOMP 报文(官方称其为 -- 发布完
成),如果发送端接收到 PUBCOMP 报文表示消息传输成功,它确认接收端已经成功接收到消息,整个过程结束,以上是?QoS2 消息传输的基本流程, MQTT 协议是如何保证接收端只能接收到一次消息的 ,这是由 MQTT 协议来控制完成的。
????????另外,要想实现 QoS>0 MQTT 通信,客户端在连接服务端时务必要将 cleanSession 设置为 false。
???????? 服务质量降级
????????
????????假如客户端 A 发布到主题 1 的消息是采用 QoS=2 ,然而客户端 B 订阅主题 1 采用 QoS = 1。在这种情况下,服务端会使用较低级别 QoS 来提供服务。虽然 A 发送到主题 1 的消息采用 QoS 为 2,但是服务端发送主题 1 的消息给 B 时,采用的 QoS 为 1。这是因为 B 在订阅主题 1 时采用的QoS 为 1。

7.保留消息

????????前面我们提到,PUBLISH 报文中有一个 retain 标志,也就是保留标志,是一个布尔值,当 retain 设置为true 时表示保留消息,如果设置为 false 表示不保留消息。

????????保留消息的作用

? ? ? ?保留消息的作用就是让服务端对客户端发布的消息进行保留,如果有其它客户端订阅了该消息对应的主题时,服务端会立即将保留消息推送给订阅者,而不必等到发送者向主题发布新消息时订阅者才会收到消息。

????????更新保留消息

????????每一个主题只能有一个“保留消息”,如果客户端想要更新“保留消息”,就需要 向该主题发送一条新的“保留消息”,这样服务端会将新的“保留消息”覆盖旧的“保留消息”。当有客户 端订阅该主题时,服务端就会将最新的“保留消息”发送给订阅者。

????????删除保留消息

????????只需要向该主题发布一条空的“保留消息”, 即可。

7.MQTT 的心跳机制

????????心跳机制的原理:让客户端在没有向服务端发送消息的这个空闲时间里,定时向服务端发送一个 心跳包,这个心跳包被称为心跳请求,其实质就是向服务端发送一个 PINGREQ 报文;当服务端收到PINGREQ报文后就知道该客户端依然在线,然后向客户端回复一个 PINGRESP 报文,称为心跳响应。通过 keepAlive 设置时间间隔,当服务器未收到客户端的心跳包,那么服务器就会知道, 这台客户端可能已经掉线了。如果客户端在发送心跳请求(PINGREQ)后,没有收到服务端的心跳响应(PINGRESP),那么客户端就会认为自己与服务端已经断开连接了。

8.MQTT 的遗嘱机制

????????客户端断开与服务端的连接通常是有两种方式的:

①客户端主动向服务端发送 DISCONNECT 报文,请求断开连接,自然服务端也就知道了客户端要离线了;
②? 客户端 意外掉线, 被动与服务端断开了连接。
? ? ? ??MQTT 从诞生之初就是专为低带宽、高延迟或不可靠网络等环境而设计的;所以针对这种意外掉线的情况,MQTT 协议使用了遗嘱机制来服务客户端、管理客户端。一旦客户端意外断线,服务端就可以将客户 端的遗嘱公之于众除了客户端主动向服务端发送 DISCONNECT 报文请求断开连接这种情况之外,其它断线的情况都属于意外断开连接。
???????? 客户端如何设置自己的“遗嘱”信息

?????????这几个参数都是以 will(遗嘱)开头的,需要在客户端连接服务端时就需要设置好:

????????willTopic -- 遗嘱主题

????????遗嘱消息和普通 MQTT 消息很相似,也有主题和正文内容。willTopic 的作用正是告知服务端,本客户端的遗嘱主题是什么。只有那些订阅了这一遗嘱主题的客户端才会收到本客户端的遗嘱消息。客户端也可以主动向遗嘱主题发布消息,这样通常会有一些妙用,譬如当客户端 A 上线时可以向自己的遗嘱主题发布一条消息,那么那些订阅了该遗嘱主题的客户端可以收到这条消息,这些订阅者也就知道了客户端 A 已经上线了。

????????willMessage -- 遗嘱消息

????????遗嘱消息定义了遗嘱的内容。在本示例中,那些订阅了主题“clientWill”的客户端会在客户端意外断线时,收到服务端发布的“client offline”这样的信息。

????????willRetain -- 遗嘱消息的保留标志

????????遗嘱消息也可以设置为保留标志,用于告诉服务端是否需要对遗嘱消息进行保留处理。

????????willQoS -- 遗嘱消息的 QoS

9.MQTT 用户密码认证

? ? ? ? CONNECT报文中还有两个参数:username(用户名)和 password(密码),这里的用户名和密码是客户端连接服务端时进行认证所需要的。有些 MQTT 服务端需要客户端在连接时提供用户名和密码,只有客户端正确提供了用户名和密码后, 才能连接服务端,否则服务端将会拒绝客户端连接。

10.公用 MQTT 服务器? ??

然也物联 ( 国内 )
官网地址: http://www.ranye-iot.net
MQTT 服务器地址: test.ranye-iot.net
TCP 端口: 1883
TCP/TLS 端口: 8883
通信猫(国内)
MQTT 服务器地址: mq.tongxinmao.com
TCP 端口: 1883

????????

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-10-08 20:58:04  更:2022-10-08 21:01:33 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 16:34:39-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码