MQTT Qos详解(一)

2023-11-18

本文基于标准MQTT讨论,不适合其他对MQTT机制做了修改的非标准MQTT协议。

 

MQTT设计了一套保证消息稳定传输的机制,包括消息应答、存储和重传。在这套机制下,提供了三种不同层次QoS(Quality of Service):

  • QoS0,发送就不管了,最多一次;
  • QoS1,发送之后依赖MQTT规范,是否启动重传消息,所以至少一次;
  • QoS2,发送之后依赖MQTT消息机制,确保只有一次。

QoS 是消息的发送方(Sender)和接受方(Receiver)之间达成的一个协议:(MQTT不是端到端的通信)

  1. QoS0 代表,Sender 发送的一条消息,Receiver 最多能收到一次,也就是说 Sender 尽力向 Receiver 发送消息,如果发送失败,也就算了;这是完全依赖TCP重传机制,如果网络不好,TCP的重传也不是100%可靠,加上MQTT是Publisher 发出去的消息是依赖代理服务器完成转发,所以消息最多一次。
  2. QoS1 代表,Sender 发送的一条消息,Receiver 至少能收到一次,也就是说 Sender 向 Receiver 发送消息,如果发送之后没有收到对应的PUBACK,就会继续重试,直到发送者Sender 接收到 Receiver 发送的 PUBACK 为止,因为重传的原因,Receiver 有可能会收到重复的消息;
  3. QoS2 代表,Sender 发送的一条消息,Receiver 确保能收到而且只收到一次,也就是说 Sender 尽力向 Receiver 发送消息,如果发送失败,会继续重试,直到 Receiver 收到消息为止,同时保证 Receiver 不会因为消息重传而收到重复的消息。(个人理解这一点有点像TCP三次握手的交互过程)

下面讨论Qos不降级的情况,即订阅者与发布者的Qos等级相同。

 

Qos 0的交互流程:

 

  1. 消息的分发依赖于底层网络的能力。接收者不会发送响应,发送者也不会重试。消息可能送达一次也可能根本没送达。消息从Publisher发送给代理服务broker,或者broker发送给Subscriher,都可能会丢失。

注意:对于QoS 0的消息, DUP标志必须设置为0 

 

Qos 1的交互流程:

 

只有当QoS等级是1或2时, 报文标识符( Packet Identifier) 字段才能出现在PUBLISH报文中。下面是MQTT Qos的补充说明:

[MQTT-4.3.2-1] 对于QoS 1的分发协议, 发送者

  • 每次发送新的应用消息都必须分配一个未使用的报文标识符。
  • MUST send a PUBLISH Packet containing this Packet Identifier with QoS=1,DUP=0。
  • 发送的PUBLISH报文必须包含报文标识符且QoS等于1,DUP等于0。
  • 必须将这个PUBLISH报文看作是 未确认的 , 直到从接收者那收到对应的PUBACK报文。 4.4节有一个关于未确认消息的讨论。

[MQTT-4.3.2-2] 对于QoS 1的分发协议, 接收者

  • 响应的PUBACK报文必须包含一个报文标识符,这个标识符来自接收到的、已经接受所有权的PUBLISH报文。
  • 发送了PUBACK报文之后,接收者必须将任何包含相同报文标识符的入站PUBLISH报文,当作一个新的消息, 并忽略它的DUP标志的值。
  1. Sender 向 Receiver 发送一个带有消息数据的 PUBLISH 包, 并在本地保存这个 PUBLISH 包。
  2. Receiver 收到 PUBLISH 包以后,向 Sender 发送一个 PUBACK 数据包,PUBACK 数据包没有消息体(Payload),在可变头中(Variable header)中有一个包标识(Packet Identifier),和它收到的 PUBLISH 包中的报文标识符(Packet Identifier) 一致。
  3. Sender 收到 PUBACK 之后,根据 PUBACK 包中的 Packet Identifier 找到本地保存的 PUBLISH 包,然后丢弃掉,一次消息的发送完成。
  4. 如果 Sender 在一段时间内没有收到 PUBLISH 包对应的 PUBACK,它将该 PUBLISH 包的 DUP 标识设为 1(代表是重新发送的 PUBLISH 包),然后重新发送该 PUBLISH 包。重复这个流程,直到收到 PUBACK,然后执行第 3 步。

注意:Qos 1代理服务器是不会进行去重的,只要发布者或者代理服务器没有收到PUBACK,就认为主题消息没有发送成功进入重发,代理服务器或者订阅者,不会根据dup的值进行去重。

        换句话说,代理服务器(broker)或者订阅者(Subscriber)在发送PUBACK报文时,(Publisher 者)发布消息主题的程序或者代理服务器(broker)的程序,已经对PUBACK报文做了判断,那么还是会重发该主题消息,并且dup标志位会+1,这样订阅者或者代理服务器就会收到多份重复的消息。并且不会去重!

 

Qos 2的交互流程:

 

只有当QoS等级是1或2时, 报文标识符( Packet Identifier) 字段才能出现在PUBLISH报文中,另外QoS 2在消息头有Message ID。下面是补充说明

[MQTT-4.3.3-1] 对于QoS 2的分发协议, 发送者

1、必须给要发送的新应用消息分配一个未使用的报文标识符。

  • MUST send a PUBLISH packet containing this Packet Identifier with QoS=2,DUP=0。

2、发送的PUBLISH报文必须包含报文标识符且报文的QoS等于2,DUP等于0。

  • 必须将这个PUBLISH报文看作是 未确认的 , 直到从接收者那收到对应的PUBREC报文。 4.4节有一个关于未确认消息的讨论。

  • 收到PUBREC报文后必须发送一个PUBREL报文。 PUBREL报文必须包含与原始PUBLISH报文相同的报文标识符。

  • 必须将这个PUBREL报文看作是 未确认的 , 直到从接收者那收到对应的PUBCOMP报文。

  • 一旦发送了对应的PUBREL报文就不能重发这个PUBLISH报文。

[MQTT-4.3.3-2] 对于QoS 2的分发协议, 接收者

  • 响应的PUBREC报文必须包含报文标识符, 这个标识符来自接收到的、 已经接受所有权的PUBLISH报文。
  • 在收到对应的PUBREL报文之前, 接收者必须发送PUBREC报文确认任何后续的具有相同标识符的PUBLISH报文。 在这种情况下, 它不能重复分发消息给任何后续的接收者。
  • 响应PUBREL报文的PUBCOMP报文必须包含与PUBREL报文相同的标识符。

        发送PUBCOMP报文之后, 接收者必须将包含相同报文标识符的任何后续PUBLISH报文当作一个新的发布。

  1. Sender 发送 QoS 为 2 的 PUBLISH 数据包,数据包包含报文标识符:Packet Identifier ,并在本地保存该 PUBLISH 包;
  2. Receiver (代理服务器或者订阅者)收到 PUBLISH 数据包以后,在本地保存 PUBLISH 包,并回复 Sender 一个 PUBREC 数据包,PUBREC 数据包可变头中的 报文标识符(Packet Identifier) 与 Sender 发送的报文标识符(Packet Identifier)一致,但是没有消息体(Payload);
  3. 当 Sender 收到 PUBREC,它就可以安全地丢弃掉初始发送的PUBLISH包,同时保存该 PUBREC 数据包,同时回复 Receiver 一个 PUBREL 数据包,PUBREL 数据包可变头中的报文标识符(Packet Identifier)保持不变,同样没有消息体(Payload);
  4. 如果 Sender 在一定时间内没有收到 PUBREC,它会把 PUBLISH 包的重发标志位 DUP 标识设为 1,重新发送该 PUBLISH 数据包(Payload);(在第三步和第四步之间是可能存在消息重传的)
  5. 当 Receiver 收到 PUBREL 数据包,它可以丢弃掉保存的 PUBLISH 包,并回复 Sender 一个 PUBCOMP 数据包,PUBCOMP 数据包可变头中的报文标识符(Packet Identifier)保持不变,没有消息体(Payload);
  6. 当 Sender 收到 PUBCOMP 包,那么它认为数据包传输已完成,它会丢弃掉对应的 PUBREC 包。如果 Sender 在一定时间内没有收到 PUBCOMP 包,它会重新发送 PUBREL 数据包。

注意:

  1. 1.Qos 2代理服务器是不会进行去重的,只要发布者或者代理服务器,没有收到PUBREC,就认为主题消息没有发送成功进入重发,代理服务器或者订阅者,不会根据dup的值进行去重。这一步会有去重,保证收到主题消息的唯一性。
  2. 发送者或者代理服务器,收到PUBREC,就认为主题消息已经发送出去,不会进行重复发送;至于订阅者,MQTT会控制显示消息,如果收到了PUBREL就认为消息已经收到,只需要在发送PUBCOMP,完成MQTT Qos 2 的交互流程。

总结:

在Qos 1 情况下,如果PUBACK超时或者发送失败,就会重传消息;

在Qos 2情况下,在没有收到PUBREC之前,也是有消息重传的可能,但是在接收到PUBREC报文之后,主题消息被删除,这样就不会对下面的交互过程产生干扰,消息在这一步之后,只能重传PUBREC、PUBREL报文。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MQTT Qos详解(一) 的相关文章

  • hi3861 通过MQTT协议连接OneNet平台(配置好的环境+详细步骤)

    目录 前言 下载配置完毕的镜像 下载链接 修改Onenet信息 添加编译 编译 烧录 HiBurn下载 查看状态 作者留言 更多详情参考gitee网站 前言 hi3861单片机通过MQTT协议连接OneNet平台 下载配置完毕的镜像 下载链
  • ESP8266_MQTT协议

    1 了解下MQTT协议 虽然上一篇用起来了MQTT 但是并不十分了解 基本就局限于 发布主题是发送数据 订阅主题是接收数据 今天就再好好了解一下吧 分享下网页版的 MQTT协议中文版 链接 Introduction MQTT协议中文版 1
  • 如何像具有 https 的网页一样设置加密的 mosquitto 代理?

    我正在尝试设置一个使用 ssl tls 加密的 mosquitto 代理 我不想生成客户端证书 我只想要一个加密连接 手册页仅描述了可用的设置 没有描述需要哪些设置以及如何使用它们 需要哪些设置以及如何设置它们 我用的是蚊子1 3 5 这里
  • 使用单连接实例实现 Eclipse MQTT Android 客户端

    我在我的应用程序中使用 Eclipse Paho android mqtt 服务 我能够订阅消息并将消息发布到 mqtt 代理 我的应用程序中有几个活动 当任何活动启动时 它都会使用以下方式连接到代理mqttAndroidClient co
  • 如何在 Eclipse PAHO Java MQTT 客户端和 Mosquitto 代理之间创建 PSK 连接?

    我正在尝试在 mosquitto mqtt 代理和使用 Eclipse Paho 客户端库的 Java 编写的应用程序之间配置预共享密钥加密连接 我已成功在两者之间建立了连接 不使用加密 而是使用 SSL 其中服务器证书经过身份验证 但没有
  • 在 Linux 上使用 cmake 独立编译 PahoMqttCpp 示例

    My goal 就是使用示例代码async subscribe cpp来自 PahoMqttCpp 项目 https github com eclipse paho mqtt cpp 作为一个独立的应用程序 然后根据我的需要对其进行修改 我
  • 为 MQTT 配置 Nginx 反向代理

    我正在尝试设置一个反向代理 将 localhost 8081 解析为安装在另一台计算机上的代理 我的 Nginx 配置文件是 worker processes 1 events worker connections 1024 server
  • 适用于 iPhone 的 MQTT 客户端

    我正在尝试遵循这个blog用于为 iPhone 构建推送服务 该博客使用 Android 作为工作平台 但它也可以迁移到 iPhone 前提是我在 Objective C 中获得了 MQTT 客户端 但我在任何地方都找不到 我最接近的是 我
  • 为什么MQTT被称为“轻量级”消息传递协议?

    As per 维基百科 and Mqtt org MQTT 是一种机器对机器 M2M 物联网 连接协议 它被设计为极轻发布 订阅消息传输 与其他 TCP IP 或基于套接字的协议相比 是什么让 MQTT 极其轻量级 MQTT的协议开销极小
  • 无法接收已发布的消息以在 mqtt paho 上订阅主题

    我正在使用 paho 发送和接收 mqtt 消息 到目前为止 发送消息没有任何问题 我在接收它们时遇到问题 我的代码是 package BenchMQTT import org eclipse paho client mqttv3 IMqt
  • python 中基于 websocket 的 MQTT

    python 是否支持通过端口 8080 订阅 mqtt 代理 import sys import paho mqtt client as mqtt def on connect mqttc obj flags rc print rc st
  • Paho MqttAndroidClient.connect 总是失败

    我想从 Android 发布消息service到本地服务器 这是我的代码的一部分 以最简单的形式基于片段here https stackoverflow com questions 24791118 android paho mqtt se
  • Mqtt 客户端如何知道另一个客户端是否已连接

    大家好 我的问题是我需要保持设备 客户端 的状态 因为它们是否在线 我通过客户端 ID 进行连接 通过订阅主题 我可以知道设备已断开连接 但如果它们再次连接 我如何检查它们是否再次连接 简而言之 你不需要 在协议级别 发布者和订阅者完全不知
  • 如何通过互联网使用 MQTT?

    目前 我正在成功运行一个 mosquitto 代理 订阅主题并与本地网络中的客户端发布消息 如何与位于不同 IP 地址的另一个本地网络进行通信 我应该设置 2 个 mosquitto 经纪人 每个本地网络一个吗 其他本地网络中的 PC 需要
  • java.io.EOFException 与 paho

    我想对蚊子进行压力测试 所以我创建了一些代码 如下所示 for int i 0 i lt 800 i final int j i Thread t new Thread new Runnable Override public void r
  • 如何使用 QtMqtt 和 SSL 执行安全 MQTT?

    我正在尝试使用 QtMQtt 示例项目 simpleclient 但我想执行安全的 MQTT 我该如何处理这个问题 我读过这篇博客 https www qt io blog 2017 08 14 introducing qtmqtt pro
  • 如何在 Android 的这个特定用例中实现 MQTT?

    我的用例 登录到我的应用程序的用户应该能够向在另一台 Android 设备上登录到该应用程序的自己发送消息 如果用户拥有多个设备 那么一旦他打开该消息 其他设备上的通知必然会消失 Doubts 如何跨设备向特定用户发送数据 我了解如何使用
  • 请求/响应的 MQTT 主题名称

    我正在设计一个包含许多设备的系统 使用 MQTT 连接到中央代理 有些主设备可以向某些从设备发送请求 来自一台主机的请求通常会发送给一台从机 请求的主题可以是 mysystem slaveId req 因此从站可以订阅该主题 并且主站可以发
  • 简化情况下能否保证mqtt消息送达顺序?

    如果只有一个代理 一个发布者 一个主题和干净的会话 在这个简化的情况下 能否保证订阅者端的消息传递顺序与发布者端的发送顺序相同 会受到QoS的影响吗 Section 4 6 http docs oasis open org mqtt mqt
  • 将消息从 AWS Lambda 发布到 AWS IoT

    我正在尝试使用 Nodejs 将消息从 AWS Lamba 发布到 AWS IoT 我已压缩该项目并上传到 AWS IoT 下面是代码片段 var awsIot require aws iot device sdk var device a

随机推荐

  • 仿射系统和非仿射系统的数学定义

    一 非仿射系统 非仿射系统是指系统的输入是以非线性的形式出现的 例如 u 2 sin u 等 12 非仿射系统可以用下面的一般形式表示 x t f x t g x t h u t 其中 x t 是状态变量 u t 是控制输入 f x 和 g
  • Codeforces-1260-E. Tournament贪心

    题目描述 You are organizing a boxing tournament where n boxers will participate n is a power of 2 and your friend is one of
  • 利用celebA数据集训练MTCNN网络

    利用celebA数据集训练MTCNN网络 celebA数据集简介 训练数据的处理 网络和训练 侦测部分 结果展示 有问题可以联系我的邮箱 2487429219 qq com 关于MTCNN网络可以看我上一篇博客 链接 人脸检测算法 mtcn
  • 请用C + +语言写一个生成随机数程序

    include
  • windows系统更改远程桌面端口

    开启远程桌面 我的电脑属性 远程设置 步骤一 在服务器运行窗口中输入 regedit 打开注册表编辑器 步骤二 在注册表HKEY LOCAL MACHINE SYSTEM CurrentControlSet Control Terminal
  • 注解-Annotation Types学习

    前言 注解是JDK5 之后推出的特性 可修饰包 类 方法 变量等 通过在编译 加载和运行时读取其信息 可执行相应的处理 基本原理 java注解类型实质上是一个标记 如 Autowired private TestBean testBean
  • win10家庭中文版开启Hyper-V功能

    问题描述 由于win10家庭中文版是被阉割过的 有些功能就被禁用了 启用和禁用程序中就没有了Hyper V功能 如果想要更多的功能可以将系统升级成为专业版和企业版即可解决 但如果想直接在家庭中文版下创建也是可行 这里有一位大神给出了自己的方
  • LeetCode题解--160. 相交链表

    题目 编写一个程序 找到两个单链表相交的起始节点 例如 下面的两个链表 A a1 a2 c1 c2 c3 B b1 b2 b3 在节点 c1 开始相交 注意 如果两个链表没有交点 返回 null 在返回结果后 两个链表仍须保持原有的结构 可
  • html5中拖放,HTML5中的拖放

    关于HTML5中的拖放 拖放 Drag 和 Drop 是一种常见的特性 即抓取对象以后拖到另一个位置 在 HTML5 中 拖放是标准的组成部分 在HTML5中用户可以使用鼠标选择一个可拖动元素 将元素拖动到一个可放置元素 并通过释放鼠标按钮
  • OpenHarmony dump渲染和合成图层SurfaceBuffer指南

    OpenHarmony dump渲染和合成图层SurfaceBuffer指南 引言 博客停更很久了 提起笔来渐感生疏啊 看来 还是得抽出时间来更新更新啊 好了 感慨也发完了 是时候切入正题了 本篇博客主要以本人在实际项目的开发中 为了定位O
  • 韩信点兵的算法

    秦朝末年 楚汉相争 韩信率兵打仗 某次 他急需点兵迎战 就命士兵布阵三次 命3人一排 多出2名 命5人一排 多出3名 命7人一排 多出2名 后 直言有1073名勇士可击垮敌兵 其神机妙算鼓舞士气 旌旗摇动 大败楚军 首先这个故事的真实性很低
  • Linux下用户的创建与删除

    我们在Linux下创建用户主要有两种方式 adduser和useradd 它们的区别以及主要用法如下 adduser adduser的用法很简单 只需adduser username即可 如下 sudo adduser alvin 这个命令
  • python深入笔记--装饰函数

    装饰函数的参数是被装饰的函数对象 返回原函数对象 装饰的实质语句 hanshu zhuangshi hanshu 第一步 最简单的函数 第二步 对函数进行装饰 hanshu zhuangshi hanshu 定义zhuangshi函数功能
  • Vue中vuex的使用(四)

    四个map方法的使用 1 mapState方法 用于帮助我们映射state中的数据为计算属性 computed 借助mapState生成计算属性 sum school subject 从state中读取数据 对象写法 mapState su
  • RISCV架构单周期CPU设计

    指令选取 R类型指令 31 25 24 20 20 19 15 14 11 7 6 0 funct7 rs2 rs1 funct3 rd opcode 编号 指令 名称 1 add rd rs1 rs2 加 2 and rd rs1 rs2
  • 6个Python童年小游戏,开始敲起来,玩吧!

    你的童年 我的童年好像都一样 谁的童年又没玩过游戏呢 这些小游戏应该只有玩过才会懂吧 虽然程序员敲代码多年 但童心还是一直都在的 今天就分享一些私藏的童年游戏 十几行代码就能进入使用Python开发的小游戏快乐玩耍 1 五子棋 童年游戏不可
  • STM32驱动_旋转编码器EC11(中断触发版本)

    STM32驱动 旋转编码器EC11 中断触发版本 说明 根据示波器测量的真实波形 可以看到 旋转编码器转动一格 实际上只有波形的一个电平变化 并不是输出一个完整周期的波形 中断触发方案 将旋转编码器的A和B两个引脚设置为A下降沿触发 B上升
  • SQL 通配符

    在 SQL 中 通配符与 SQL LIKE 操作符一起使用 SQL 通配符用于搜索表中的数据 在 SQL 中 可使用以下通配符 通配符 描述 替代 0 个或多个字符 替代一个字符 charlist 字符列中的任何单一字符 charlist
  • 家庭IOT监测之摄像头数据上传ONENET

    本篇目标 将摄像头OV7670的照片数据 转换成BMP二进制 上传到ONENET平台 用于远程监测 材料准备 之前移植的温湿度及红外修改工程 温湿度及红外修改工程 继续往里面移植摄像头驱动上传代码 STM32F407最终摄像头上传ONENE
  • MQTT Qos详解(一)

    本文基于标准MQTT讨论 不适合其他对MQTT机制做了修改的非标准MQTT协议 MQTT设计了一套保证消息稳定传输的机制 包括消息应答 存储和重传 在这套机制下 提供了三种不同层次QoS Quality of Service QoS0 发送