MQTT笔记
在了解MQTT之前先认识网络互联的七层模型OSI一文彻底搞懂OSI七层模型和TCP/IP四层模型
OSI网络七层模型:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层
TCP/IP四层模型:应用层、传输层、网络层、网络接口层
层级 | 名称 | 核心作用 | 常见协议或技术 | 典型设备或概念 |
---|---|---|---|---|
第7层 | 应用层 | 为应用程序提供网络服务接口,定义用户与网络的交互规则 | HTTP/HTTPS、FTP、SMTP、DNS、DHCP、SNMP | 应用程序、浏览器、邮件客户端 |
第6层 | 表示层 | 数据表示与兼容性处理:编码/解码、加密/解密、压缩/解压缩、字符集转换 | ASCII/Unicode、JPEG、MPEG、TLS/SSL | 加密库、编解码器 |
第5层 | 会话层 | 建立、管理与终止会话,支持会话恢复与同步(如断点续传) | RPC、NetBIOS、会话控制协议 | 会话控制器 |
第4层 | 传输层 | 提供端到端通信,分段/重组,流量控制与差错恢复;协议有TCP(可靠)/UDP(尽力而为) | TCP、UDP | 端口、套接字 |
第3层 | 网络层 | 逻辑寻址(IP)与路由选择,跨网络转发数据包,处理拥塞控制 | IP、ICMP、ARP、OSPF、BGP、RIP | 路由器、三层交换机 |
第2层 | 数据链路层 | 将数据封装为帧,MAC寻址,差错检测(如CRC),流量控制,介质访问控制(如CSMA/CD) | 以太网、PPP、HDLC、Wi‑Fi(MAC层)、VLAN | 交换机、网桥、网卡(NIC) |
第1层 | 物理层 | 在物理介质上传输比特流(0/1),定义电压、时序、引脚、线缆、光纤、连接器等 | RJ45、RS‑232、光纤、IEEE 802.3(以太网物理层) | 中继器、集线器 |
MQTT位于OSI 第7层 应用层;在TCP/IP 四层模型中同样属于应用层,并且运行在 TCP 之上。这意味着它负责定义应用如何通过主题进行消息发布与订阅、会话管理等语义,而不处理底层的可靠传输细节(由TCP负责)
MQTT介绍
MQTT(Message Queuing Telemetry Transport)是一种面向物联网的轻量级、发布/订阅消息协议,运行在TCP/IP之上,由IBM在1999年提出,2014年成为 OASIS 标准,2016年被采纳为 ISO/IEC 20922:2016 国际标准。其设计目标是在低带宽、不稳定、资源受限的网络中实现可靠的消息传输。常见误解是名称含“消息队列”——MQTT并非传统消息队列,而是基于Broker的消息转发与会话机制。典型上层端口与形态包括:1883(未加密)、8883(MQTT over TLS)、8083、(MQTT over WebSocket),以及轻量变体 MQTT‑SN(面向受限设备与非 IP 网络)
角色与术语
- 客户端(Client):设备或应用,可发布、订阅或同时进行。
- 代理(Broker):消息中枢,负责连接管理、主题匹配、会话与消息转发。
- 主题(Topic):UTF‑8 字符串,层级用/分隔(如:sensors/room1/temp)。
- 主题过滤器(Topic Filter):订阅时使用,支持通配符:+(单级)、#(多级,必须在末尾)。
会话与消息留存
- Clean Session:false 时为持久会话,Broker 保存订阅与离线 QoS 1/2 消息,重连后继续投递。
- 保留消息(Retained):发布时设置,Broker 保留最新一条,新订阅者立即收到。
- 遗嘱消息(Last Will and Testament, LWT):连接异常断开时,Broker 代发预设主题与消息,用于告警。
心跳与保活
- 使用 PINGREQ/PINGRESP 心跳维持连接,默认间隔由 KeepAlive 控制,超时未响应则判定离线。
QoS 等级与流程
- QoS 0:最多一次(≤1),无确认与重传,低开销。
- QoS 1:至少一次(≥1),发送方保存直到收到 PUBACK,可能重复。
- QoS 2:恰好一次(=1),四次握手 PUBLISH→PUBREC→PUBREL→PUBCOMP,开销最大但最可靠
MQTT工作原理
MQTT 是基于发布-订阅模式的通信协议,由 MQTT 客户端通过主题(Topic)发布或订阅消息,通过 MQTT Broker 集中管理消息路由,并依据预设的服务质量等级(QoS)确保端到端消息传递可靠性。,实现一对多的消息分发机制,消息不是直接从发送器发送到接收器(即点对点),而是由MQTT server(或称为 MQTT Broker)分发的
这幅图中:温度传感器将温度的信息发布到Temperature主题上,三个客户端都对Temperatrue主题进行订阅得到温度信息,代理服务器充当信息的留存于转发。
MQTT的消息格式
固定头(Fixed header),存在于所有MQTT数据包中,表示数据包类型及数据包的分组类标识;
可变头(Variable header),存在于部分MQTT数据包中,数据包类型决定了可变头是否存在及其具体内容;
消息体(Payload),存在于部分MQTT数据包中,表示客户端收到的具体内容;
固定头(Fixed header)
MQTT固定报文头最少有两个字节,第一字节包含消息类型(Message Type)和QoS级别等标志位。第二字节开始是剩余长度字段,该长度是后面的可变报文头加消息负载的总长度,该字段最多允许四个字节。
剩余长度字段单个字节最大值为二进制0b0111 1111,16进制0x7F。也就是说,单个字节可以描述的最大长度是127字节。为什么不是256字节呢?因为MQTT协议规定,单个字节第八位(最高位)若为1,则表示后续还有字节存在,第八位起“延续位”的作用。
例如,数字64,编码为一个字节,十进制表示为64,十六进制表示为0×40。数字321(65+2*128)编码为两个字节,重要性最低的放在前面,第一个字节为65+128=193(0xC1),第二个字节是2(0x02),表示2×128。
由于MQTT协议最多只允许使用四个字节表示剩余长度(如表1),并且最后一字节最大值只能是0x7F不能是0xFF,所以能发送的最大消息长度是256MB,而不是512MB。
可变头(Variable Header)
可变报文头主要包含:
- 协议名
- 协议版本
- 连接标志(Connect Flags)
- 心跳间隔时间(Keep Alive timer)
- 连接返回码(Connect Return Code)
- 主题名(Topic Name)
消息体(Payload)
当MQTT发送消息的类型为下面类型时,则会带有消息主体:
- CONNECT:连接
- PUBLISH:发布
- SUBSCRIBE:订阅
- SUBACK:订阅确认
- UNSUBSCRIBE:取消订阅
MQTT的消息特性
消息类型(message type)
在 固定头(Fixed header) 中的第一个字节,包含 “连接标志(Connect Flag)”,用来区分MQTT的消息类型。
名称 | 值 | 流方向 | 描述 |
---|---|---|---|
Reserved | 0 | 不可用 | 保留位 |
CONNECT | 1 | 客户端到服务器 | 客户端请求连接到服务器 |
CONNACK | 2 | 服务器到客户端 | 连接确认 |
PUBLISH | 3 | 双向 | 发布消息 |
PUBACK | 4 | 双向 | 发布确认 |
PUBREC | 5 | 双向 | 发布收到(保证第1部分到达) |
PUBREL | 6 | 双向 | 发布释放(保证第2部分到达) |
PUBCOMP | 7 | 双向 | 发布完成(保证第3部分到达) |
SUBSCRIBE | 8 | 客户端到服务器 | 客户端请求订阅 |
SUBACK | 9 | 服务器到客户端 | 订阅确认 |
UNSUBSCRIBE | 10 | 客户端到服务器 | 请求取消订阅 |
UNSUBACK | 11 | 服务器到客户端 | 取消订阅确认 |
PINGREQ | 12 | 客户端到服务器 | PING请求 |
PINGRESP | 13 | 服务器到客户端 | PING应答 |
DISCONNECT | 14 | 客户端到服务器 | 中断连接 |
Reserved | 15 | 不可用 | 保留位 |
这14种消息类型,可以简单地分为:
- 连接及断开连接
- 发布及订阅
- QoS 2消息的机制
- 各种确认ACK
DUP标识位
DUP(Duplicate)是 MQTT PUBLISH 报文固定头中的1 位标志,位于固定头第 1 字节的bit 3。
1、含义:
- DUP=0:表示这是客户端或服务端对该 PUBLISH 的第一次发送尝试。
- DUP=1:表示这可能是该 PUBLISH 的重发(retransmission)。
2、用途:
在不可靠网络下,发送方(客户端或 Broker)对未确认的 QoS 1/2 PUBLISH 进行重传时,将 DUP 置 1,以便接收方识别这是重发报文(用于去重、重传控制等实现层面)。•
3、重要澄清:
Broker 在将收到的 PUBLISH 转发给订阅者时,不会传播原始报文中的 DUP 标志;Broker 发出的下行 PUBLISH 自身是否置 DUP=1,只取决于 Broker 自身是否在对上行 PUBLISH 做重发,与上游报文的 DUP 无关。
接收方收到 DUP=1 的 PUBLISH,不能据此认定应用层消息“已经收到过”;DUP 只对控制报文本身有意义,不等同于“消息重复”
消息质量(QoS)
MQTT消息质量有三个等级,QoS 0,QoS 1和 QoS 2。
- QoS 0:最多分发一次。消息的传递完全依赖底层的TCP/IP网络,协议里没有定义应答和重试,消息要么只会到达服务端一次,要么根本没有到达。
- QoS 1:至少分发一次。服务器的消息接收由PUBACK消息进行确认,如果通信链路或发送设备异常,或者指定时间内没有收到确认消息,发送端会重发这条在消息头中设置了DUP位的消息。
- QoS 2:只分发一次。这是最高级别的消息传递,消息丢失和重复都是不可接受的,使用这个服务质量等级会有额外的开销。
QoS 0 ~ 2 等级的应用,用共享单车举例:
- QoS 0 最多一次:智能锁定时发送共享单车位置,一次失败了没关系,过段时间还会再次发送
- QoS 1 至少一次:开锁
- QoS 2 正好一次:骑车完付钱
发布保留标识(RETAIN)
表示服务器要保留这次推送的信息,如果有新的订阅者出现,就把这消息推送给它,如果设有那么推送至当前订阅者后释放。
遗愿标志(Will Flag)
在可变报头的连接标志位字段(Connect Flag)里有三个Will标志位:
- Will Flag
- Will QoS
- Will Retain Flag
这些Will字段用于监控客户端与服务器之间的连接状况。如果设置了Will Flag, 则必须设置Will QoS和Will Retain,消息主体中也必须有Will Topic和Will Message字段。
遗愿消息是怎么回事呢?当客户端与服务端通信时,当遇到异常或客户端心跳超时时,MQTT服务器会替客户端发一个Will消息。
当如果服务器收到来自客户端的DISCONNECT消息,则不会触发Will消息的发送。
因此,Will字段应用于设备掉线后,需要通知用户的场景。
连接保活机制(Keep Alive Timer)
MQTT客户端可以设置一个心跳间隔时间(Keep Alive Timer),表示在每个心跳时间内发送一条消息。如果在这个时间周期内,没有业务数据相关的消息,客户端会发一个PINGREQ消息,相应的,服务器会返回一个PINGRESP消息进行确认。如果服务器在一个半(1.5)心跳周期内没有收到来自客户端的消息,就会断开与客户端的连接。心跳间隔时间最大值大约可以设为18个小时,0值意味着客户端不断开。
参考:
MQTT是什么
MQTT协议详解(完整版)