MQTT协议及其控制报文种类详解
目录
一. 介绍OneNET平台
1.1 OneNET平台简介
1、OneNET 是中移物联网有限公司自主研发的国家级物联网 PaaS 开放平台
2、OneNET支持适配各种网络环境和协议类型,可实现各种传感器和智能硬件的快速接入,提供丰富的API和应用模板以支撑各类行业应用和智能硬件的开发,有效降低物联网应用开发和部署成本,满足物联网领域设备连接、协议适配、数据存储、数据安全以及大数据分析等平台级服务需求。
1.2 主流接入协议
| 套件 | 适用场景 | 协议特点 |
|---|---|---|
| MQTT 套件 | 实时双向通信(单片机、WiFi 设备、4G 模组) | 轻量、发布订阅、支持命令下发,最通用 |
| NB-IoT LwM2M 套件 | 低功耗广覆盖(水表、烟感、路灯) | CoAP 底层、省电、心跳保活、适合电池供电设备 |
| Modbus 套件 | 工业现场(PLC、变频器、DTU) | 适配工业串口设备,寄存器自动解析 |
| HTTP/HTTPS 套件 | 简单单向上报(一次性采集设备) | 无长连接,开发最简单,不适合实时控制 |
| TCP 泛协议套件 | 私有自定义设备协议 | 支持脚本解析自定义报文,兼容非标硬件 |
二. 介绍MQTT协议
2.1 MQTT简介
MQTT(Message Queuing Telemetry Transport, 消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的"轻量级"通讯协议,该协议构建于TCP/IP协议上,由IBM在1999年发布。MQTT最大优点在于,可以以极少的代码和有限的带宽,为远程连接设备提过实时可靠的消息服务,作为一种低开销、低带宽占用的即时通讯协议,使其在物联网、小型设备、移动应用等方面有较广泛的应用
MQTT是一个基于客户端-服务器的消息发布/订阅传输协议。MQTT协议是轻量、简单、开放和易于实现的,这些特点使它适用范围非常广泛。在很多情况下,包括受限的环境中,如:机器与机器(M2M)通信和物联网(loT)。其在,通过卫星链路通信传感器、偶尔拨号的医疗设备、智能家居、及一些小型化设备中已广泛使用。

主流版本:MQTT 3.1.1(嵌入式设备通用)
MQTT 是单片机、WiFi、4G 模组、智能控制器上云首选,兼顾低功耗、双向控制、低流量,绝大多数物联网监测、控制类项目都会选用
2.1 MQTT特点
2.1.1 基于发布/订阅模式
MQTT是一种轻量级的物联网通信协议,基于发布/订阅模式,支持QoS级别,适用于低带宽、高延迟的网络环境。它具有精简的协议设计,开放的消息协议,以及广泛应用于物联网、M2M通信、消息推送和智能设备等领域。MQTT协议涉及发布者、订阅者和消息代理(Broker)的角色,以及连接、订阅、发布消息的过程,并包含会话保持和心跳机制,确保消息的可靠传输。
发布者和订阅者不需要直接建立连接,借助第三方代理broker,发布者与代理软件连接,将数据发给代理,订阅者与代理进行连接,代理将数据发给订阅者

2.1.2 请求与响应模式
客户端向服务端发送请求,服务端收到请求后,向客户端返回响应

2.1.3 支持QoS服务质量
可靠传输保证;有三种消息发布服务质量:
QoS=0:“至多一次”,消息发布完全依赖底层TCP/IP网络。会发生消息丢失或重复。这一级别可用于如下情况,环境传感器数据,丢失一次读记录无所谓,因为不久后还会有第二次发送。这一种方式主要普通APP的推送,倘若你的智能设备在消息推送时未联网,推送过去没收到,再次联网也就收不到了。
QoS=1:“至少—次”,确保消息到达,但消息重复可能会发生。
QoS=2:“只有一次”,确保消息到达一次。在一些要求比较严格的计费系统中,可以使用此级别。在计费系统中,消息重复或丢失会导致不正确的结果。这种最高质量的消息发布服务还可以用于即时通讯类的APP的推送,确保用户收到且只会收到一次。
2.1.4 心跳保活机制
连接时约定 Keepalive 心跳时间,设备定时发送 PINGREQ 维持长连接; 长时间无心跳平台判定设备离线,自动推送离线事件,适合无人值守传感器
2.1.5 支持双向通信,支持云端下发指令
不像 HTTP 只能设备主动上传;MQTT 长连接支持平台主动下发控制命令(开关、采集、重启),完美适配远程控制类设备。
2.1.6 其他特点
轻量级:占用系统资源较少,数据报文较小
可靠性强:提供了多种消息的质量等级
安全性较强:提供了传输层与套接层的加密功能
双向通信:发布者与订阅者都可以对broker进行收发数据
多编程语言支持
2.2 MQTT常见概念
2.2.1 MQTT客户端
任何运行mqtt客户端库(mqtt开发工具包)的应用或者设备都是mqtt客户端
2.2.2 MQTT的代理broker
实现了mqtt通信协议的代理软件
2.2.3 主题
存在于mqtt的broker中,就是一个普通字符串,使用主题来对消息进行分类的
三. MQTT控制报文格式
3.1 MQTT 控制报文的结构
MQTT 协议通过预定义的 MQTT 控制报文来通信。 这一节描述这些报文的格式。MQTT 控制报文由以下三部分组成:

3.2 固定报头Fixed header
每个 MQTT 控制报文都包含一个固定报头。
3.2.1 固定报头的格式
固定报头格式如下:
三部分:mqtt control packet type + flags + remaining length
报文类型 4bits+ 报文标识位 4bits+ 剩余长度1~4byte

1、MQTT控制报文类型
mqtt control packet type
1、位置: 第 1 个字节, 二进制位 7-4,表示为 4 位无符号值
2、具体信息如下表,可以看到总共有14种可用报文的类型
| 名字 | 值 | 报文流动方向 | 描述 |
| Reserved | 0 | 禁止 | 保留 |
| CONNECT | 1 | 客户端到服务端 | 客户端请求连接服务端 |
| CONNACK | 2 | 服务端到客户端 | 连接报文确认 |
| PUBLISH | 3 | 两个方向都允许 | 发布消息 |
| PUBACK | 4 | 两个方向都允许 | QoS 1 消息发布收到确认 |
| PUBREC | 5 | 两个方向都允许 | 发布收到(保证交付第一步) |
| PUBREL | 6 | 两个方向都允许 | 发布释放(保证交付第二步) |
| PUBCOMP | 7 | 两个方向都允许 | QoS 2 消息发布完成(保证交互第三步) |
| SUBSCRIBE | 8 | 客户端到服务端 | 客户端订阅请求 |
| SUBACK | 9 | 服务端到客户端 | 订阅请求报文确认 |
| UNSUBSCRIBE | 10 | 客户端到服务端 | 客户端取消订阅请求 |
| UNSUBACK | 11 | 服务端到客户端 | 取消订阅报文确认 |
| PINGREQ | 12 | 客户端到服务端 | 心跳请求 |
| PINGRESP | 13 | 服务端到客户端 | 心跳响应 |
| DISCONNECT | 14 | 客户端到服务端 | 客户端断开连接 |
| Reserved | 15 | 禁止 | 保留 |
2、用于指定控制报文类型的标志位
flags
1、固定报头第 1 个字节的剩余的 4 位 [3-0]包含每个 MQTT 控制报文类型特定的标志,如下表所示。
2、表格中任何标记为“保留”的标志位, 都是保留给以后使用的,必须设置为表格中列出的值 如果收到非法的标志, 接收者必须关闭网络连接。
3、可以看到,只有PUBLISH报文的这四个比特位被赋予了明确的含义:
bit3:表示当前PUBLISH报文是否是一个重传报文
bit2/1:表示当前PUBLISH报文使用的服务质量等级
bit0:表示当前PUBLISH报文是否是一个保留消息
| 控制报文 | 固定报头标志 | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
| CONNECT | Reserved | 0 | 0 | 0 | 0 |
| CONNACK | Reserved | 0 | 0 | 0 | 0 |
| PUBLISH | Used in MQTT 3.1.1 | DUP1 | QoS2 | QoS2 | RETAIN3 |
| PUBACK | Reserved | 0 | 0 | 0 | 0 |
| PUBREC | Reserved | 0 | 0 | 0 | 0 |
| PUBREL | Reserved | 0 | 0 | 1 | 0 |
| PUBCOMP | Reserved | 0 | 0 | 0 | 0 |
| SUBSCRIBE | Reserved | 0 | 0 | 1 | 0 |
| SUBACK | Reserved | 0 | 0 | 0 | 0 |
| UNSUBSCRIBE | Reserved | 0 | 0 | 1 | 0 |
| UNSUBACK | Reserved | 0 | 0 | 0 | 0 |
| PINGREQ | Reserved | 0 | 0 | 0 | 0 |
| PINGRESP | Reserved | 0 | 0 | 0 | 0 |
| DISCONNECT | Reserved | 0 | 0 | 0 | 0 |
3、剩余长度
remaining length
1、剩余长度(Remaining Length) 表示当前报文剩余部分的字节数, 包括可变报头和负载的数据。 剩余长度不包括用于编码剩余长度字段本身的字节数。
剩余长度=可变报头+有效载荷
2、剩余长度字段使用一个变长度编码方案, 对小于 128 的值它使用单字节编码。 更大的值按下面的方式处理:低 7 位有效位用于编码数据,最高有效位用于指示是否有更多的字节。 因此每个字节可以编码 128 个数值和一个延续位(continuation bit)。
3、剩余长度字段最大 4 个字节。剩余长度字段的大小如下表所示
分别表示(每个字节的低 7 位用于编码数据, 最高位是标志位) :
1 个字节时, 从 0(0x00)到 127(0x7f)
2 个字节时, 从 128(0x80,0x01)到 16383(0Xff,0x7f)
3 个字节时, 从 16384(0x80,0x80,0x01)到 2097151(0xFF,0xFF,0x7F)
4 个字节时, 从 2097152(0x80,0x80,0x80,0x01)到 268435455(0xFF,0xFF,0xFF,0x7F)
4、这允许应用发送最大 256MB(268,435,455)大小的控制报文。这个数值在报文中的表示是:0xFF,0xFF,0xFF,0x7F。
| 字节数 | 最小值 | 最大值 |
| 1 | 0 (0x00) | 127 (0x7F) |
| 2 | 128 (0x80, 0x01) | 16 383 (0xFF, 0x7F) |
| 3 | 16 384 (0x80, 0x80, 0x01) | 2 097 151 (0xFF, 0xFF, 0x7F) |
| 4 | 2 097 152 (0x80, 0x80, 0x80, 0x01) | 268 435 455 (0xFF, 0xFF, 0xFF, 0x7F) |
这一块比较难懂,举例说明:
例一:
假设可变报头+有效载荷总共100字节
由于剩余长度一字节可以表示 0~127 故,直接使用 0x64 表示即可
例二:
假设可变报头+有效载荷总共200字节
由于剩余长度一字节可以表示 0~127 故,直接一字节明显不够表示,应该使用两字节表示,详细过程如下:

例三:
假设可变报头+有效载荷总共1000字节
同理可知,剩余长度要两字节,由例二的过程可得,剩余长度最终为:E8 07
例四:
假设可变报头+有效载荷总共20000字节
同理可知,剩余长度要三字节,由例二的过程可得,剩余长度最终为:A0 9C 01
3.3 可变报头Variable header
3.3.1 报文标识符
1、某些 MQTT 控制报文包含一个可变报头部分。 它在固定报头和负载之间。可变报头的内容根据报文类型的不同而不同。可变报头的报文标识符(Packet Identifier)字段存在于在多个类型的报文里。

2、很多控制报文的可变报头部分包含一个两字节的报文标识符字段。 这些报文是 PUBLISH(QoS>0 时),PUBACK, PUBREC, PUBREL, PUBCOMP, SUBSCRIBE, SUBACK, UNSUBSCIBE,UNSUBACK。
3、SUBSCRIBE, UNSUBSCRIBE 和 PUBLISH(QoS 大于 0) 控制报文必须包含一个非零的 16 位报文标识符(Packet Identifier)。客户端每次发送一个新的这些类型的报文时都必须分配一个当前未使用的报文标识符。 如果一个客户端要重发这个特殊的控制报文,在随后重发那个报文时, 它必须使用相同的标识符。 当客户端处理完这个报文对应的确认后,这个报文标识符就释放可重用。
QoS = 1 的 PUBLISH 对应的是 PUBACK, QoS = 2 的 PUBLISH 对应的是 PUBCOMP,与 SUBSCRIBE 或UNSUBSCRIBE 对应的分别是 SUBACK 或 UNSUBACK 。 发送一个 QoS = 0 的 PUBLISH报文时, 相同的条件也适用于服务端 。
4、QoS 设置为 0 的 PUBLISH 报文不能包含报文标识符
5、PUBACK, PUBREC, PUBREL 报文必须包含与最初发送的 PUBLISH 报文相同的报文标识符 。 类似地, SUBACK 和 UNSUBACK 必须包含在对应的 SUBSCRIBE 和 UNSUBSCRIBE 报文中使用的报文标识符
需要报文标识符的控制报文如下表所示
| 控制报文 | 报文标识符字段 |
| CONNECT | 不需要 |
| CONNACK | 不需要 |
| PUBLISH | 需要(如果 QoS > 0) |
| PUBACK | 需要 |
| PUBREC | 需要 |
| PUBREL | 需要 |
| PUBCOMP | 需要 |
| SUBSCRIBE | 需要 |
| SUBACK | 需要 |
| UNSUBSCRIBE | 需要 |
| UNSUBACK | 需要 |
| PINGREQ | 不需要 |
| PINGRESP | 不需要 |
| DISCONNECT | 不需要 |
3.4 有效载荷 Payload
1、某些 MQTT 控制报文在报文的最后部分包含一个有效载荷,用于实现对应报文的核心功能。
2、对于 PUBLISH 来说,有效载荷就是应用消息。 下表列出了需要有效载荷的控制报文。
| 控制报文 | 有效载荷 |
| CONNECT | 需要 |
| CONNACK | 不需要 |
| PUBLISH | 可选 |
| PUBACK | 不需要 |
| PUBREC | 不需要 |
| PUBREL | 不需要 |
| PUBCOMP | 不需要 |
| SUBSCRIBE | 需要 |
| SUBACK | 需要 |
| UNSUBSCRIBE | 需要 |
| UNSUBACK | 不需要 |
| PINGREQ | 不需要 |
| PINGRESP | 不需要 |
| DISCONNECT | 不需要 |
四. MQTT十四种控制报文详解
4.1 CONNECT 连接报文--1号
1、客户端到服务端的网络连接建立后,客户端发送给服务端的第一个报文必须是 CONNECT 报文
2、在一个网络连接上,客户端只能发送一次 CONNECT 报文。服务端必须将客户端发送的第二个CONNECT报文当作协议违规处理并断开客户端的连接
3、有效载荷包含一个或多个编码的字段。 包括客户端的唯一标识符, Will 主题, Will 消息, 用户名和密码。 除了客户端标识之外, 其它的字段都是可选的, 基于标志位来决定可变报头中是否需要包含这些字段
4.1.1 固定报头
CONNECT的固定报头,两字节:10 ??(这是剩余长度,可变)
剩余长度:等于可变报头的长度(10 字节) 加上有效载荷的长度

4.1.2 可变报头
1、CONNECT 报文的可变报头按下列次序包含四个字段:协议名(Protocol Name) , 协议级别(ProtocolLevel) , 连接标志(Connect Flags)和保持连接(Keep Alive)
协议名:
六字节:00 04 4D 51 54 54

协议级别:
对于 3.1.1 版协议,协议级别字段的值是 4(0x04)。 如果发现不支持的协议级别, 服务端必须给发送一个返回码为 0x01(不支持的协议级别) 的 CONNACK 报文响应CONNECT 报文, 然后断开客户端的连接
一字节:04

连接标志:
一字节:C2

用户名标志:位置: 连接标志的第 7 位。
如果用户名(User Name) 标志被设置为 0, 有效载荷中不能包含用户名字段
如果用户名(User Name) 标志被设置为 1, 有效载荷中必须包含用户名字段
密码标志:位置: 连接标志的第 6 位。
如果密码(Password) 标志被设置为 0, 有效载荷中不能包含密码字段
如果密码(Password) 标志被设置为 1, 有效载荷中必须包含密码字段
如果用户名标志被设置为 0, 密码标志也必须设置为 0
保持连接:
两字节:eg:00 64 ---->表示超过(1.5x100)秒内没有发数据就断开连接

注意:
1、 保持连接(Keep Alive) 是一个以秒为单位的时间间隔,表示为一个 16 位的字,它是指在客户端传输完成一个控制报文的时刻到发送下一个报文的时刻, 两者之间允许空闲的最大时间间隔。 客户端负责保证控制报文发送的时间间隔不超过保持连接的值。 如果没有任何其它的控制报文可以发送, 客户端必须发送一个PINGREQ 报文----保活包、心跳包
2、不管保持连接的值是多少,客户端任何时候都可以发送 PINGREQ 报文,并且使用 PINGRESP 报文判断网络和服务端的活动状态。
3、如果保持连接的值非零,并且服务端在一点五倍的保持连接时间内没有收到客户端的控制报文, 它必须断开客户端的网络连接, 认为网络连接已断开
4、客户端发送了 PINGREQ 报文之后, 如果在合理的时间内仍没有收到 PINGRESP 报文, 它应该关闭到服务端的网络连接。
5、保持连接的值为零表示关闭保持连接功能。 这意味着,服务端不需要因为客户端不活跃而断开连接。 注意:不管保持连接的值是多少, 任何时候,只要服务端认为客户端是不活跃或无响应的, 可以断开客户端的连接。
4.1.3 有效载荷
1、CONNECT 报文的有效载荷(payload) 包含一个或多个以长度为前缀的字段,可变报头中的标志决定是否包含这些字段。 如果包含的话, 必须按这个顺序出现:客户端标识符, 遗嘱主题, 遗嘱消息, 用户名, 密码
客户端标识符:
1、服务端使用客户端标识符 (ClientId) 识别客户端。 连接服务端的每个客户端都有唯一的客户端标识符(ClientId) 。客户端和服务端都必须使用 ClientId 识别两者之间的 MQTT 会话相关的状态
2、客户端标识符 (ClientId) 必须存在而且必须是 CONNECT 报文有效载荷的第一个字段
3、先是2字节的数据长度,后面才是客户端标识符
用户名:
1、如果用户名(User Name) 标志被设置为 1, 有效载荷的下一个字段就是它。 服务端可以将它用于身份验证和授权
2、先是2字节的数据长度,后面才是用户名
密码:
1、如果密码(Password) 标志被设置为 1, 有效载荷的下一个字段就是它。密码字段包含一个两字节的长度字段, 长度表示二进制数据的字节数(不包含长度字段本身占用的两个字节) , 后面跟着 0 到 65535 字节的二进制数据。
2、先是2字节的数据长度,后面才是密码

4.2 CONNACK 确认连接报文--2号
1、服务端发送 CONNACK 报文响应从客户端收到的 CONNECT 报文。服务端发送给客户端的第一个报文必须是 CONNACK
2、如果客户端在合理的时间内没有收到服务端的 CONNACK 报文, 客户端应该关闭网络连接。 合理的时间取决于应用的类型和通信基础设施
3、此报文无有效载荷
4.2.1 固定报头
两字节:20 02
剩余长度固定为 02

4.2.2 可变报头
两字节:一般是 00 00
连接确认标志+连接返回码

连接返回码:

4.3 DISCONNECT 断开连接报文--14号
1、DISCONNECT 报文是客户端发给服务端的最后一个控制报文。表示客户端正常断开连接
2、此报文没有可变报头与有效载荷
4.3.1 固定报头
两字节:E0 00

4.4 PINGREQ 心跳请求报文--12号
1、客户端发送 PINGREQ 报文给服务端的。用于:
在没有任何其它控制报文从客户端发给服务的时,告知服务端客户端还活着。
请求服务端发送 响应确认它还活着。
使用网络以确认网络连接没有断开。
2、此报文没有可变报头与有效载荷
4.4.1 固定报头
两字节:C0 00

4.5 PINGRESP 心跳响应报文--13号
1、服务端发送 PINGRESP 报文响应客户端的 PINGREQ 报文。 表示服务端还活着
2、此报文没有可变报头与有效载荷
4.5.1 固定报头
两字节:D0 00

4.6 SUBSCRIBE 订阅主题报文--8号
1、客户端向服务端发送 SUBSCRIBE 报文用于创建一个或多个订阅。 每个订阅注册客户端关心的一个或多个主题。 为了将应用消息转发给与那些订阅匹配的主题, 服务端发送 PUBLISH 报文给客户端。 SUBSCRIBE报文也(为每个订阅) 指定了最大的 QoS 等级, 服务端根据这个发送应用消息给客户端。
4.6.1 固定报头
两字节:82 ??(剩余长度)

4.6.2 可变报头
报文标识符(两字节):示例:00 0A
报文标识符相当于一个消息ID

4.6.3 有效载荷
表示订阅谁
长度与主题:示例:00 30(两字节的长度) 后面是主题
服务质量等级:00 00(阿里云支持0/1)
1、SUBSCRIBE 报文的有效载荷包含了一个主题过滤器列表, 它们表示客户端想要订阅的主题 。服务端应该支持包含通配符的主题过滤器。 如果服务端选择不支持包含通配符的主题过滤器, 必须拒绝任何包含通配符过滤器的订阅请求 。 每一个过滤器后面跟着一个字节, 这个字节被叫做服务质量要求(Requested QoS) 。它给出了服务端向客户端发送应用消息所允许的最大 QoS 等级。
2、SUBSCRIBE 报文的有效载荷必须包含至少一对主题过滤器 和 QoS 等级字段组合。没有有效载荷的SUBSCRIBE 报文是违反协议的

4.7 SUBACK 订阅确认报文--9号
1、服务端发送 SUBACK 报文给客户端, 用于确认它已收到并且正在处理 SUBSCRIBE 报文
4.7.1 固定报头
两字节:90 ??(剩余长度)

4.7.2 可变报头
报文标识符:(与SUBSCRIBE一致):示例:00 0A

4.7.3 有效载荷
1、允许的返回码值:
0x00 - 最大 QoS 0
0x01 - 成功 – 最大 QoS 1
0x02 - 成功 – 最大 QoS 2
0x80 - Failure 失败
2、00(在OneNET平台,SUBSCRIBE不管是0还是1,回复的都是0)

4.8 UNSUBSCRIBE 取消订阅报文--10号
1、客户端发送 UNSUBSCRIBE 报文给服务端, 用于取消订阅主题
4.8.1 固定报头
两字节:A2 ??(剩余长度)

4.8.2 可变报头
报文标识符:示例:00 0A

4.8.3 有效载荷
1、长度与主题:(两字节的长度) 后面是主题
2、这个报文无服务质量等级,故与SUBSCRIBE相比,剩余长度会少一个字节
一个示例:

4.9 UNSUBACK 取消订阅确认--11号
1、此报文无有效载荷
2、服务端发送 UNSUBACK 报文给客户端用于确认收到 UNSUBSCRIBE 报文
4.9.1 固定报头
两字节:B0 02(剩余长度)
剩余长度固定为02

4.9.2 可变报头
报文标识符(与SUBSCRIBE一致):示例:00 0A
由于只有两字节的报文标识符,故剩余长度固定为02

4.10 PUBLISH 发布消息报文--3号
1、PUBLISH 控制报文是指从客户端向服务端或者服务端向客户端传输一个应用消息
2、客户端使用 PUBLISH 报文发送应用消息给服务端, 目的是分发到其它订阅匹配的客户端。
3、服务端使用 PUBLISH 报文发送应用消息给每一个订阅匹配的客户端。
4.10.1 固定报头
30(DUP,QoS,RETAIN都是0)
重发标志DUP
服务质量等级QoS

保留标志RETAIN
??(可变长度)

4.10.2 可变报头
报文标识符:只有在qos等于1/2时才有,故:00
主题名长度+主题名
一个示例:

4.10.3 有效载荷
1、发送的数据
2、数据内容(这一块不用数据长度+数据内容),因为剩余长度-可变报头的长度就是有效载荷的长度
3、有效载荷包含将被发布的应用消息。 数据的内容和格式是应用特定的。 有效载荷的长度这样计算: 用固定报头中的剩余长度字段的值减去可变报头的长度。 包含零长度有效载荷的 PUBLISH 报文是合法的
4.11 PUBACK 发布确认报文--4号
1、PUBACK 报文是对 QoS 1 等级的 PUBLISH 报文的响应
2、此报文无有效载荷
4.11.1 固定报头
40 02

4.11.2 可变长度
包含等待确认的 PUBLISH 报文的报文标识符。

4.12 PUBREC 发布收到报文--5号
1、此报文无有效载荷
2、PUBREC 报文是对 QoS 等级 2 的 PUBLISH 报文的响应。它是 QoS 2 等级协议交换的第二个报文
4.12.1 固定报头
50 02

4.12.2 可变报头
报文标识符
可变报头包含等待确认的 PUBLISH 报文的报文标识符

4.13 PUBREL 发布释放报文--6号
1、此报文无有效载荷
2、PUBREL 报文是对 PUBREC 报文的响应。 它是 QoS 2 等级协议交换的第三个报文。
4.13.1 固定报头
62 02

4.13.2 可变报头
报文标识符
可变报头包含与等待确认的 PUBREC 报文相同的报文标识符

4.14 PUBCOMP 发布完成报文--7号
1、此报文无有效载荷
2、PUBCOMP 报文是对 PUBREL 报文的响应。 它是 QoS 2 等级协议交换的第四个也是最后一个报文。
4.14.1 固定报头
70 02

4.14.2 可变报头
可变报头包含与等待确认的 PUBREL 报文相同的报文标识符。

更多推荐

所有评论(0)