解密MQTT协议:从QOS到消息传递的全方位解析
1、QoS介绍
1.1、QoS简介
使用MQTT协议的设备大部分都是运行在网络受限的环境下,而只依靠底层的TCP传输协议,并不
能完全保证消息的可靠到达。
MQTT提供了QoS机制,其核心是设计了多种消息交互机制来提供不同的服务质量,来满足用
户在各种场景下对消息可靠性的要求。
MQTT 定义了三个 QoS 等级,分别为:
1、QoS 0,最多交付一次 -----> 可能丢失消息
2、QoS 1,至少交付一次 -----> 可以保证收到消息,但消息可能重复
3、QoS 2,只交付一次 -----> 可以保证消息既不丢失也不重复
QoS等级是由发布者在PUBLISH报文中指定的,大部分情况下Broker向订阅者转发消息时都会维
持原始的 QoS 不变。不过也有一些例外的情况,根据订阅者的订阅要求,
消息的 QoS 等级可能会在转发的时候发生降级。
例如,订阅者在订阅时要求Broker可以向其转发的消息的最大QoS等级为QoS 1,那么后续所有
QoS 2消息都会降级至QoS 1转发给此订阅者,而所有QoS 0和QoS 1消息
则会保持原始的QoS等级转发。

1.2、QoS 0原理介绍
1.2.1、通讯原理说明
QoS 0 是最低的 QoS 等级。QoS 0 消息即发即弃,不需要等待确认,不需要存储和重传,因此对
于接收方来说,永远都不需要担心收到重复的消息。

涉及到的相关报文:

1.2.2、Qos 0消息丢失原因
当我们使用 QoS 0 传递消息时,消息的可靠性完全依赖于底层的 TCP 协议。而 TCP 只能保证在
连接稳定不关闭的情况下消息的可靠到达,一旦出现连接关闭、重置,
仍有可能丢失当前处于网络链路或操作系统底层缓冲区中的消息。这也是 QoS 0 消息最主要的丢
失场景。
1.3、Qos 1原理介绍
1.3.1、通讯原理说明
为了保证消息到达,QoS 1 加入了应答与重传机制,发送方只有在收到接收方的 PUBACK 报文以
后,才能认为消息投递成功,在此之前,发送方需要存储该 PUBLISH 报文以便下次重传。

QoS 1需要在 PUBLISH 报文中设置 Packet ID,而作为响应的 PUBACK 报文,则会使用与
PUBLISH 报文相同的 Packet ID,以便发送方收到后删除正确PUBLISH报文缓存。
涉及到的相关报文:

1.3.2、Qos 1消息会重复原因
对于发送方来说,没收到 PUBACK 报文分为以下两种情况:
1、PUBLISH 未到达接收方
2、PUBLISH 已经到达接收方,接收方的 PUBACK 报文还未到达发送方
在第一种情况下,发送方虽然重传了 PUBLISH 报文,但是对于接收方来说,实际上仍然仅收到了
一次消息。
在第二种情况下,在发送方重传时,接收方已经收到过了这个 PUBLISH 报文,这就导致接收方将
收到重复的消息。

重传 PUBLISH 报文的时候,PUBLISH 中的 DUP 标志会被设置为 1,用以表示这是一个重传的报
文。
1.4、Qos 2原理介绍
1.4.1、通讯原理说明
QoS 2 解决了 QoS 0、1 消息可能丢失或者重复的问题,但相应地,它也带来了最复杂的交互流程
和最高的开销。每一次的 QoS 2 消息投递,都要求发送方与接收方进行至少两次请求/响应流
程。

流程说明:
1、首先,发送方存储并发送 QoS 为 2 的 PUBLISH 报文以启动一次 QoS 2 消息的传输,然后等
待接收方回复 PUBREC 报文。这一部分与 QoS 1 基本一致,只是响应报文从 PUBACK 变成了
PUBREC。
2、当发送方收到 PUBREC 报文,即可确认对端已经收到了 PUBLISH 报文,发送方将不再需要重
传这个报文,并且也不能再重传这个报文。所以此时发送方可以删除本地1存储的 PUBLISH 报
文,然后发送一个 PUBREL 报文,通知对端自己准备将本次使用的 Packet ID 标记为可用了。与
PUBLISH 报文一样,我们需要确保 PUBREL报文到达对端,所以也需要一个响应报文,并且这个
PUBREL 报文需要被存储下来以便后续重传。
3、当接收方收到 PUBREL 报文,也可以确认在这一次的传输流程中不会再有重传的 PUBLISH 报
文到达,因此回复 PUBCOMP 报文表示自己也准备好将当前的 PacketID 用于新的消息了。
4、当发送方收到 PUBCOMP 报文,这一次的 QoS 2 消息传输就算正式完成了。在这之后,发送
方可以再次使用当前的 Packet ID 发送新的消息,而接收方再次收到使用这个 Packet ID 的
PUBLISH 报文时,也会将它视为一个全新的消息。
涉及到的报文:

1.4.2、Qos 2消息不会重复原因
消息不丢失原因:与 QoS 1 相同
消息不会重复原因:
快速回顾一下 QoS 1 消息无法避免重复的原因:
当我们使用 QoS 1 消息时,对接收方来说,回复完 PUBACK 这个响应报文以后 Packet ID 就重新
可用了,也不管响应是否确实已经到达了发送方。所以就无法得知之后到达的,携带了相同
Packet ID 的 PUBLISH 报文,到底是发送方因为没有收到响应而重传的,还是发送方因为收到了
响应所以重新使用了这个 Packet ID 发送了一个全新的消息。

所以,消息去重的关键就在于,通信双方如何正确地同步释放 Packet ID,换句话说,不管发送方
是重传消息还是发布新消息,一定是和对端达成共识了的。而 QoS 2中增加的 PUBREL 流程,正
是提供了帮助通信双方协商 Packet ID 何时可以重用的能力。

QoS 2 规定,发送方只有在收到 PUBREC 报文之前可以重传 PUBLISH 报文。一旦收到 PUBREC 报
文并发出 PUBREL 报文,发送方就进入了 Packet ID 释放流程,不可以再使用当前 Packet ID 重
传 PUBLISH 报文。同时,在收到对端回复的 PUBCOMP 报文确认双方都完成 Packet ID 释放之
前,也不可以使用当前Packet ID 发送新的消息。

因此,对于接收方来说,能够以 PUBREL 报文为界限,凡是在 PUBREL 报文之前到达的
PUBLISH 报文,都必然是重复的消息;而凡是在 PUBREL 报文之后到达的
PUBLISH 报文,都必然是全新的消息。一旦有了这个前提,我们就能够在协议层面完成 QoS 2 消
息的去重。
相关文章:
解密MQTT协议:从QOS到消息传递的全方位解析
1、QoS介绍 1.1、QoS简介 使用MQTT协议的设备大部分都是运行在网络受限的环境下,而只依靠底层的TCP传输协议,并不 能完全保证消息的可靠到达。 MQTT提供了QoS机制,其核心是设计了多种消息交互机制来提供不同的服务质量,来满足…...
Java-02 深入浅出 MyBatis - MyBatis 快速入门(无 Spring) POM Mapper 核心文件 增删改查
点一下关注吧!!!非常感谢!!持续更新!!! 大数据篇正在更新!https://blog.csdn.net/w776341482/category_12713819.html 目前已经更新到了: MyBatisÿ…...
Unity功能模块一对话系统(4)实现个性文本标签
本期我们将了解如何在TMPro中自定义我们的标签样式,并实现两种有趣的效果。 一.需求描述 1.定义<float>格式的标签,实现标签处延迟打印功能 2.定义<r" "></r>格式的标签,实现标签区间内文本片段的注释显示功能…...
git在idea中操作频繁出现让输入token或用户密码,可以使用凭证助手(使用git命令时输入的用户密码即可) use credential helper
1、打开 idea 设置,找到 git 路径 File | Settings | Version Control | Git 2、勾选 Use credential helper 即可...
毫米波雷达技术:(九)快时间窗和慢时间窗的概念
(一)快时间窗: 快时间窗通常指的是在雷达脉冲周期内,对每个脉冲回波进行采样的时间段。这个时间段非常短,通常在 0 − 100 n s 0-100ns 0−100ns 。在快时间窗内,雷达系统会对接收到的回波信号进行高分辨…...
宠物行业的出路:在爱与陪伴中寻找增长新机遇
在当下的消费市场中,如果说有什么领域能够逆势而上,宠物行业无疑是一个亮点。当人们越来越注重生活品质和精神寄托时,宠物成为了许多人的重要伴侣。它们不仅仅是家庭的一员,更是情感的寄托和生活的调剂。然而,随着行业…...
Android MQTT关于断开连接disconnect报错原因
最近项目遇到一个需求,就是在登录状态的时候。才能接收到消息。所有我在上线,下线状态的时候。做了MQTT断开和连接的动作。然后就是发生了。我们标题的这关键点了。直接报错了。报错的内容如下: MqttAndroidClient unregisterRecevicer afte…...
Unity3D中Huatuo可行性的思维实验详解
引言 Unity3D作为一款功能强大的跨平台游戏引擎,在游戏开发领域具有举足轻重的地位。它不仅支持2D和3D游戏开发,还广泛应用于虚拟现实、建筑可视化等领域。其中,Huatuo作为一个强大的热更新解决方案,通过扩展Unity的IL2CPP运行时…...
ES-聚合分析
ES的聚合分析 什么是ES的聚合分析 ElasticSearch除搜索意外,提供的针对ES数据进行统计分析的功能通过聚合,我们会得到一个数据的概览,是分析和总结全套的数据,而不是寻找单独的文档高性能,只要一条语句就可以得到分析…...
【CSS in Depth 2 精译_093】16.2:CSS 变换在动效中的应用(上)—— 图标的放大和过渡效果的设置
当前内容所在位置(可进入专栏查看其他译好的章节内容) 第五部分 添加动效 ✔️【第 16 章 变换】 ✔️ 16.1 旋转、平移、缩放与倾斜 16.1.1 变换原点的更改16.1.2 多重变换的设置16.1.3 单个变换属性的设置 16.2 变换在动效中的应用 ✔️ 16.2.1 放大图…...
Linux Debian安装ClamAV和命令行扫描病毒方法,以及用Linux Shell编写了一个批量扫描病毒的脚本
ClamAV是一个开源的跨平台病毒扫描引擎,用于检测恶意软件、病毒、木马等安全威胁。 一、Linux Debian安装ClamAV 在Linux Debian系统上安装ClamAV,你可以按照以下步骤进行: 更新软件包列表: 打开终端并更新你的软件包列表&#…...
Spring创建异步线程,使用@Async注解时不指定value可以吗?
在Spring中使用Async注解时,不指定value是可以的。如果没有指定value(即线程池的名称),Spring会默认使用名称为taskExecutor的线程池。如果没有定义taskExecutor线程池,则Spring会自动创建一个默认的线程池。 默认行为…...
二分和离散化
为什么把二分和离散化放一起:因为离散化其实是一种二分整数的过程。 二分 相信大家都接触过二分查找(折半查找),这就是二分的思想。 二分通过每次舍弃一半并不存在答案的区间,进而快速锁定要求的答案(二…...
深度学习实战102-基于深度学习的网络入侵检测系统,利用各种AI模型和pytorch框架实现网络入侵检测
大家好,我是微学AI,今天给大家介绍一下深度学习实战102-基于深度学习的网络入侵检测系统,利用各种AI模型和pytorch框架实现网络入侵检测。近年来,网络安全威胁日益严峻,传统基于规则的方法难以应对复杂多变的入侵手段。 深度学习技术凭借其强大的特征学习能力和自适应性,…...
vue3使用element-plus,解决 el-table 多选框,选中后翻页再回来选中失效问题
问题:勾选的数据分页再回来回消失 1.在el-table中加 :row-key"getRowKey" const getRowKey (row) > { return row.id; // id必须是唯一的 }; 2.给type为selection的el-table-column添加上reserve-selection属性 <el-tableref"multipleTab…...
网络的类型
BMA---广播型多路访问--在一个网段内可以放置多个物理节点,同时该范围内可以实施广播洪泛机制 【1】以太网-->共享型 属性典型的 BMA类型;以太网技术的核心为频分一在同一物理介质上,使用多个相互不干涉的频率电波来共同传输数据,实现带宽的不断提升…...
实现类似gpt 打字效果
1. css的动画(animation) css中实现动画有两种方式:transition过渡动画、 animation自定义动画。 具体的可以看MDN链接:https://developer.mozilla.org/zh-CN/docs/Web/CSS/animation 使用keyframes自定义关键帧动画并未其命名使用自定义动…...
项目需求分析流程
项目需求分析是软件开发或任何工程项目中至关重要的第一步。它帮助确保团队理解客户的需求,并为后续的设计、开发和测试工作提供指导。以下是一个详细的需求分析流程: 一、确定项目目标 与利益相关者沟通:包括但不限于客户、最终用户、销售…...
idea连接SQL Server数据库_idea连接sqlserver数据库
4.设置密码(这一步可以在安装数据库时就可以完成),如果觉得用户名有问题,也可以修改用户名 5.查看SQL Server端口号(默认端口:1433),选择SQL Server2019配置管理器 6.打开SQL Server…...
Scala_【2】变量和数据类型
第二章 注释标识符的命名规范命名规则关键字 变量字符串输出数据类型关系变量和数据类型整数类型(Byte、Short、Int、Long)浮点类型(Float、Double)字符类型(Char)布尔类型(Boolean)…...
Phi-4-reasoning-vision-15B行业应用:银行手机银行截图→交易流程合规性审计
Phi-4-reasoning-vision-15B在银行手机银行截图合规审计中的应用实践 1. 银行业务合规审计的痛点与机遇 在银行业务数字化转型的浪潮中,手机银行已成为客户办理业务的主要渠道。然而,随之而来的是海量的交易截图和操作记录需要人工审核,以确…...
极简音乐工具:重新定义纯粹听歌体验
极简音乐工具:重新定义纯粹听歌体验 【免费下载链接】tonzhon-music 铜钟 (Tonzhon.com): 免费听歌; 没有直播, 社交, 广告, 干扰; 简洁纯粹, 资源丰富, 体验独特!(密码重置功能已回归) 项目地址: https://gitcode.com/GitHub_Trending/to/tonzhon-mus…...
Rockchip Android13 x3588 USB 2.0硬件调试与DTS配置实战
1. RK3588 USB 2.0硬件基础与问题定位 最近在调试x3588开发板的USB 2.0接口时,遇到了设备无法识别的问题。这个问题在嵌入式开发中很常见,但排查过程却需要系统性的思路。先说说RK3588的USB架构特点,这颗芯片的USB控制器设计相当灵活…...
AtlasOS终极指南:专业解决Windows安装错误2502/2503的完整方案
AtlasOS终极指南:专业解决Windows安装错误2502/2503的完整方案 【免费下载链接】Atlas 🚀 An open and lightweight modification to Windows, designed to optimize performance, privacy and security. 项目地址: https://gitcode.com/GitHub_Trendi…...
Realistic Vision V5.1显存占用对比:启用offload前后VRAM峰值下降62%实测
Realistic Vision V5.1显存占用对比:启用offload前后VRAM峰值下降62%实测 1. 项目背景与技术特点 Realistic Vision V5.1是目前Stable Diffusion 1.5生态中最顶级的写实风格模型之一,能够生成媲美专业单反相机拍摄的人像作品。然而在实际使用中&#x…...
用PyTorch从零搭建U-Net:手把手教你搞定遥感图像分割(附完整代码)
用PyTorch从零搭建U-Net:手把手教你搞定遥感图像分割(附完整代码) 遥感图像分割是计算机视觉领域的重要应用方向,尤其在农业监测、城市规划、灾害评估等场景中发挥着关键作用。对于刚接触深度学习实践的开发者来说,从…...
实战电商用户行为分析:基于Dinky+Flink SQL构建实时数仓(Kafka→HBase→Doris全链路)
电商用户行为实时分析实战:基于Dinky与Flink SQL的全链路实现 电商平台每天产生海量用户行为数据,如何实时处理这些数据并快速生成业务洞察,成为提升用户体验和商业价值的关键。本文将手把手带你构建一个完整的实时分析系统,从Kaf…...
CC Switch模型测试功能:构建可靠AI服务的全周期验证方法论
CC Switch模型测试功能:构建可靠AI服务的全周期验证方法论 【免费下载链接】cc-switch A cross-platform desktop All-in-One assistant tool for Claude Code, Codex & Gemini CLI. 项目地址: https://gitcode.com/GitHub_Trending/cc/cc-switch [问题发…...
数电技术实战解析04:CMOS门电路设计与优化
1. CMOS反相器:数字世界的开关艺术 第一次拆解CMOS反相器时,我被它的精妙设计震撼到了——就像家里电灯的双控开关,只不过这个"开关"的尺寸只有头发丝的万分之一。这个由PMOS和NMOS管组成的经典结构,构成了所有数字电路…...
Cesium实战:手把手教你实现智慧城市中的动态流动线(附完整代码与避坑指南)
Cesium实战:打造智慧城市动态流动线的完整技术方案 在数字孪生和智慧城市可视化项目中,动态流动线是实现交通流、管网流向等动态效果的关键元素。本文将深入探讨如何基于Cesium引擎,从Shader编写到前端集成,构建高性能的动态线可视…...
