码农知识堂 - 1000bd
Python
PHP
JS/TS
JAVA
C/C++
C#
GO
Kotlin
Swift
MQTT协议基础学习
MQTT
是什么
MQTT是一个
客户端
服务端架构的发布/订阅模式的消息传输协议。
MQTT基本原理
MQTT服务端
MQTT服务端通常是一台服务器,可对MQTT信息的接收、储存、处理和发送。
负责将MQTT客户端发送来的信息传递给其他MQTT客户端(需要客户端订阅)。确保客户端之间的通讯顺畅,保证MQTT消息得以正确接收和准确投递。
负责管理MQTT客户端。
MQTT客户端
发布行为——向服务端发布信息。
接收行为——从服务端收取信息。需要先要向服务端“订阅”信息(即告诉服务端需要哪些信息)。
既可以作为信息发布者也可以同时作为信息订阅者。
MQTT主题
MQTT服务端在管理MQTT信息通讯时,就是使用“主题”来控制的。
当某客户端向主题发送信息后,服务端会首先检查都有哪些客户端订阅了这一主题,再将信息转发给订阅了该主题的客户端。
主题基本形式
主题是区分大小写的。motor_speed和Motor_speed是两个完全不同的主题。
主题可以使用空格。如current time,虽然有空格分隔current和time这两个词,但这实际是一个MQTT主题。
大部分MQTT服务端是不支持中文主题的。应使用英文字符或ASCII字符来作为MQTT主题。
主题分级
MQTT主题可以是一个简单的字符串,比如motor_speed,myTopic。这些都是单一级别的主题。
为了更好的对主题进行管理和分类,可对主题进行分级处理。MQTT主题各个级别之间可以使用”/”来分隔。
单级通配符:+
单级通配符可以代替一个主题级别。
示例:home/sensor/
+
/temperature,可以收到home/sensor/
kitchen
/temperature、home/sensor/
bedroom
/temperature主题的信息内容。
多级通配符:#
多级通配符”#”可以涵盖任意数量的主题级别。应放在最后
主题应用注意事项
以$开始的主题是MQTT服务端系统保留的特殊主题,我们不能随意订阅或者向其发布信息。
$SYS/broker/clients/connected
$SYS/broker/clients/disconnected
$SYS/broker/clients/total
$SYS/broker/messages/sent
$SYS/broker/uptime
不要用 “/” 作为主题开头
主题中不要使用空格
保持主题简洁明了
主题中尽量使用ASCII字符
在主题中嵌入客户端ID:通过主题中的客户端ID内容,我们可以很容易的了解该主题信息是由哪一台设备所发布的
MQTT 发布/订阅 特性
相互可独立。MQTT客户端是一个个独立的个体,它们无需了解彼此的存在,依然可以实现信息交流。
空间可分离。MQTT客户端在通讯必要条件是连接到了同一个MQTT通讯网络。这个网络可以是互联网或者局域网。只要客户端联网,无论他们远在天边还是近在眼前,都可以实现彼此间的通讯交流。
时间可异步。MQTT客户端在发送和接收信息时无需同步。当客户端离线后,MQTT服务端可以将主题的新信息保存,待客户端再次上线后,服务端再将信息推送给客户端。
连接MQTT服务端
第一步:发送连接请求
CONNECT数据报文的作用:告诉服务端,客户端与服务端通信的模式。
clientId:客户端ID。同一个服务端不可重复,客户端身份标识
cleanSession:清除会话。true,告诉客户端不要保存任何会话内容;false,告诉客户端需要保存会话内容。客户端收到信息后需向服务端反馈“我已收到”,若客户端未反馈,服务端会保存会话内容并重复发送。
请注意
,如果需要服务端保存重要报文,光设置cleanSession 为false是不够的,还需要传递的MQTT信息QoS级别大于0。
keepAlive:心跳时间间隔(单位秒)。定期告诉服务端客户端的连接状态。
第二步:连接确认
CONNACK数据报文的作用:向客户端发送连接确。
returnCode:连接返回码。说明连接情况。数字0,表示成功连接。
sessionPresent:当前会话。客户端与服务端cleanSession为false时,服务端会保存客户端未确认收到的信息。true:服务端告诉客户端有未确认的消息;false:表示客户端所有消息都已正常发送并接收。
发布、订阅、取消订阅
发布
MQTT客户端一旦连接到服务端,便可以发布消息。
每条发布的MQTT消息必须包含一个主题。
MQTT服务器可以通过主题确定将消息转发给哪些客户端。
MQTT客户端发布消息时,会向服务端发送PUBLISH报文。
topicName:主题名称。用于识别此信息应发布到哪一个主题。
qos:服务质量等级。QoS有三个级别:0、1和2(重要性一次增高)。QoS决定MQTT通讯有什么样的服务保证。
packetId:报文标识符。同的MQTT报文所拥有的标识符不同。MQTT设备可以通过该标识符对MQTT报文进行甄别和管理。
请注意
:报文标识符的内容与QoS级别有密不可分的关系。只有QoS级别大于0时,报文标识符才是非零数值。如果QoS等于0,报文标识符为0。
retainFlag :保留标志。false:发布
非保留消息
。当客户端订阅了某一主题后,并不会马上接收到该主题的信息。只有在客户端订阅该主题后,服务端接收到该主题的新信息时,服务端才会将最新接收到的该主题信息推送给客户端。true:发布
保留消息
。客户端在订阅了某一主题后马上接收到一条该主题的信息(因为服务端保留了最新的payload)。
payload:有效载荷。通过MQTT所发送的实际内容。可以发送文本,图像等格式的内容。
dupFlag :重复标志。true:接收方没有及时确认收到报文时,发送方会重复发送MQTT报文。
请注意
,重发标志只在QoS级别大于0时使用。
订阅
客户端是通过向服务端发送SUBSCRIBE报文来实现主题订阅。
请留意
,一个SUBSCRIBE报文可以包含有单个或者多个订阅主题名。
客户端在订阅主题时也可以明确QoS。服务端会根据SUBSCRIBE中的QoS来提供相应的服务保证。
每一个SUBSCRIBE报文还包含有“报文标识符”。
订阅确认
服务端接收到客户端的订阅报文后,会向客户端发送SUBACK报文确认订阅。
packetId:报文标识符。
returnCode :订阅返回码。服务端会针对SUBSCRIBE报文中的所有订阅主题来逐一回复给客户端一个返回码。针对不同的主题订阅QoS,服务端的返回码会有所不同。
取消订阅
客户端向服务端发送UNSUBSCRIBE报文取消订阅。
同一个UNSUBSCRIBE报文可以同时包含多个取消订阅的主题名称。
UNSUBSCRIBE报文也包含“报文标识符”,MQTT设备可以通过该标识符对报文进行管理。
取消订阅确认
服务端接收到UNSUBSCRIBE报文后,会向客户端发送取消订阅确认报文 – UNSUBACK报文。该报文含有客户端所发送的“取消订阅报文标识符”。客户端接收到UNSUBACK报文后就可以确认取消主题订阅已经成功完成了。
Qos 服务质量等级
告知物联网系统,哪些信息是重要信息需要准确无误的传输,而哪些信息不那么重要,即使丢失也没有问题。
Qos三种服务质量级别
Qos=数字0,最多发一次
MQTT服务端和客户端不会对消息传输是否成功进行确认和检查。消息能否成功传输全看网络环境是否稳定。
也就是说,在QoS为0时。发送端一旦发送完消息后,就完成任务了。发送端不会检查发出的消息能否被正确接收到。
Qos=数字1,最少发一次(可能重复接收)
发送端将消息发送给接收端后,会等待接收端的确认。接收端成功接收消息后,会发送一条确认报文PUBACK给发送端。如果发送端收到了这条PUBACK确认报文,那么它就知道消息已经成功接收。
若发送端没有收到PUBACK报文,那么发送端会再次发送消息,然后再次等待接收端的PUBACK确认报文。因此,当QoS=1时,发送端在没有收到接收端的PUBACK确认报文以前,会重复发送同一条消息。
当发送端重复发送一条消息时,PUBLISH报文中的dupFlag会被设置为True。这是为了告诉接收端,此消息为重复发送的消息。
Qos=数字2,保证只收一次
发送端需要接收端进行两次消息确认。①发送端发送Qos=2的PUBLISH报文给接收端。②接收端收到QoS为2的消息后,会返回PUBREC报文作为应答。③发送端收到PUBREC报文后,会把此报文进行存储,并且返回PUBREL报文作为应答。④当接收端收到PUBREL报文后,会应答发送端一条PUBCOMP报文。
设置Qos
Qos=1
接收端连接服务端时需将CONNECT报文中cleanSession设置为false
接收端订阅主题时SUBSCRIBE数据包中QoS=1
发布端发布消息时PUBLISH数据包中QoS=1
Qos=2
接收端连接服务端时需将CONNECT报文中cleanSession设置为false
接收端订阅主题时SUBSCRIBE数据包中QoS=2
发布端发布消息时PUBLISH数据包中QoS=2
服务质量降级(最低级原则)
假如客户端在发布和订阅信息时使用不同级别的QoS,服务端会主动采用较低级别的QoS来实现消息传输。
情况一:发布端发布消息时PUBLISH数据包中QoS=2,接收端订阅主题时SUBSCRIBE数据包中QoS=1。此时,服务端向接收端发送消息时,采用的Qos为1。
情况二:发布端发布消息时PUBLISH数据包中QoS=0,接收端订阅主题时SUBSCRIBE数据包中QoS=1。此时,服务端向接收端发送消息时,采用的Qos为0。
小结
若想实现QoS>0,订阅端连接服务端时cleanSession需要设置为false,订阅端订阅主题时QoS>0,发布端发布消息时的QoS>0。
服务端会选择发布消息和订阅消息中较低的QoS来实现消息传输,这也被称作“服务降级”。
QoS = 0, 占用的网络资源最低,但是接收端可能会出现无法接收消息的情况,所以适用于传输重要性较低的信息。
QoS = 1, MQTT会确保接收端能够接收到消息,但是有可能出现接收端反复接收同一消息的情况。
QoS = 2, MQTT会确保接收端只接收到一次消息。但是QoS为2时消息传输最慢,另外消息传输需要多次确认,因此所占用的网络资源也是最多的。此类服务等级适用于重要消息传输。
由于QoS1和QoS2都能确保客户端接收到消息,但是QoS1所占用的资源较QoS2占用资源更小。因此建议使用QoS1来实现网络资源较为珍贵的环境下传输重要信息。
心跳机制
服务端可以使用类似心跳检测的方法,来判断客户端是否在线。
客户端在没有向服务端发送信息时,可以定时向服务端发送一条消息。这条用于心跳机制的消息也被称作心跳请求(PINGREQ)。
服务端在收到客户端的心跳请求后,会回复一条消息。这条回复消息被称作心跳响应(PINGRESP)。
由于心跳请求是客户端定时发送的,一旦服务端发现客户端停止发送请求信息,那么服务端就会知道,这台客户端已经断开了连接。同时,也可用于客户端判断自己与服务端是否保持连接。
设置心跳间隔
在客户端连接服务端时,会将心跳时间间隔信息放入CONNECT报文中keepAlive字段(单位秒)。
心跳机制详情
客户端在心跳时间间隔内发布了消息给服务端,那么服务端不需要客户端发送心跳请求也可以确定该客户端肯定在线。
客户端在心跳间隔内没有发布消息给服务端,这时客户端会主动发送一个心跳请求消息给服务端。以表明自己仍让在线。
在实际运行中,如果服务端没有在1.5倍心跳时间间隔内收到客户端发布消息(PUBLISH)或发来心跳请求(PINGREQ),那么服务端就会认为这个客户端已经掉线。举例来说,如果心跳时间间隔是60秒。那么服务端在90秒内没有收到客户端发布的消息也没有收到PINGREQ请求,那么它就会认为客户端已经掉线。
MQTT遗嘱
MQTT协议允许客户端在“活着”的时候就写好遗嘱,这样一旦客户端
意外断线
,服务端就可以将客户端的遗嘱公之于众。客户端的遗嘱只在意外断线时才会发布,如果客户端正常的断开了与服务端的连接,这个遗嘱机制是不会启动的,服务端也不会将客户端的遗嘱公布。
服务端在没有收到DISCONNECT报文的情况下,发现客户端“心跳”停止了,这时服务端就知道客户端是意外断线了。
客户端正常断开连接时,会向服务端发送DISCONNECT报文,服务端接收到该报文后,就知道,客户端是正常断开连接,而并非意外断开连接。
客户端如何将遗嘱消息发送给服务端
在上图的CONNECT报文中,使用红色对一系列信息进行了标注。客户端正是在连接服务端时,利用这一系列信息将遗嘱消息发送给服务端。
lastWillTopic :遗嘱主题。遗嘱消息和普通MQTT消息很相似,也有主题和正文内容。
lastWillMessage :遗嘱消息(遗嘱正文)。只有那些订阅了遗嘱主题的客户端才会收到本客户端的遗嘱消息。
lastWillQoS :遗嘱QoS。使用服务质量来控制遗嘱消息的传递和接收。(与普通MQTT消息的服务质量是一样0、1、2三个级别)
lastWillRetain :遗嘱保留。设置遗嘱消息是否需要进行保留处理。
遗嘱操作注意事项
假设我们现在有一台MQTT客户端。它的client id是 client-1。它的遗嘱主题是“client-1-will”
当client-1连接服务端时,CONNECT报文中的遗嘱消息是“offline”。并且它的遗嘱保留设置为true。
当client-1成功连接服务端后,立即向遗嘱主题“client-1-will”发布一条消息“online”。同时在发布此消息时,保留标志设置为true。这样,只要client-1在线,那么任何设备一订阅“client-1-will”就能收到设备在线的消息“online”。
如果client-1发生意外离线。那么任何设备一订阅“client-1-will”就会收到设备离线的消息”offline”。
如果client-1恢复连接,那么它会将遗嘱主题“client-1-will”的保留消息更改为“online”,这样任何设备一订阅“client-1-will”就能收到设备在线的消息“online”。
特别感谢
教程来源:
太极创客
相关阅读:
【无标题】
内卷时代下的前端技术-使用JavaScript在浏览器中生成PDF文档
迭代器 Iterator
检验检疫系统(LIS)源码:C# + MVC + SQLserver + Redis
Postgresql支持的浮点类型和区别案例
基于学生成绩管理系统(附源代码及数据库)
(PyTorch)PyTorch中的常见运算(*、@、Mul、Matmul)
vite-vue3-ts 搭建项目时 项目中使用 @ 指代 src
微软校园大使喊你来秋招啦!
生产者-消费者问题
原文地址:https://blog.csdn.net/github_33809414/article/details/134248953
最新文章
攻防演习之三天拿下官网站群
数据安全治理学习——前期安全规划和安全管理体系建设
企业安全 | 企业内一次钓鱼演练准备过程
内网渗透测试 | Kerberos协议及其部分攻击手法
0day的产生 | 不懂代码的"代码审计"
安装scrcpy-client模块av模块异常,环境问题解决方案
leetcode hot100【LeetCode 279. 完全平方数】java实现
OpenWrt下安装Mosquitto
AnatoMask论文汇总
【AI日记】24.11.01 LangChain、openai api和github copilot
热门文章
十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
奉劝各位学弟学妹们,该打造你的技术影响力了!
五年了,我在 CSDN 的两个一百万。
Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
面试官都震惊,你这网络基础可以啊!
你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
心情不好的时候,用 Python 画棵樱花树送给自己吧
通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
13 万字 C 语言从入门到精通保姆级教程2021 年版
10行代码集2000张美女图,Python爬虫120例,再上征途
Copyright © 2022 侵权请联系
2656653265@qq.com
京ICP备2022015340号-1
正则表达式工具
cron表达式工具
密码生成工具
京公网安备 11010502049817号