1. MQTT 的定位
MQTT(Message Queuing Telemetry Transport)是一个轻量级发布/订阅消息协议,专为 低带宽、低功耗、不稳定网络 设计,广泛用于物联网(IoT)。
2. MQTT 在网络协议栈中的位置
MQTT 属于 应用层协议,其依赖关系如下:
┌───────────────────────┐
│ MQTT 协议 │ ← 应用层
└───────────────────────┘
┌───────────────────────┐
│ TCP 协议 │ ← 可靠的传输层
└───────────────────────┘
┌───────────────────────┐
│ IP 协议(IPv4/6) │ ← 网络层
└───────────────────────┘
┌───────────────────────┐
│ 数据链路层(WiFi/以太网)│
└───────────────────────┘⭐ MQTT 只能跑在 TCP 上(默认 1883 端口,TLS 加密 8883)。
它不支持 UDP,因为 MQTT 依赖 TCP 的:
- 顺序保证
- 重传机制
- 可靠连接
3. MQTT 数据包结构(TCP 之上的协议结构)
MQTT 报文结构由三部分组成:
┌───────────────────────────┐
│ Fixed Header(固定报头) │ ← 强制存在
├───────────────────────────┤
│ Variable Header(可变报头)│ ← 部分报文存在
├───────────────────────────┤
│ Payload(有效负载) │ ← 部分报文存在
└───────────────────────────┘以下详细解释:
3.1 🔷 Fixed Header(固定报头)
固定报头由 2 部分组成:
① 第一个字节:报文类型 + Flag
bit 7-4 :Message Type(报文类型)
bit 3-0 :Flags(标志位,依报文类型而变)示例:
| 类型 | 编号 | 说明 |
|---|---|---|
| CONNECT | 1 | 客户端请求连接 |
| PUBLISH | 3 | 发布消息 |
| SUBSCRIBE | 8 | 订阅消息 |
| PINGREQ | 12 | 心跳请求 |
例如一个 PUBLISH 报文首字节可能是:
0011 1100 (0x3C)② 第二部分:Remaining Length(剩余长度)
采用 可变长度编码(类似 protobuf)。
可用 1〜4 个字节表示整个剩余部分的长度。
示例:
| 字节 | 值 | 表示 |
|---|---|---|
| 0x7F | 127 | 用 1 个字节 |
| 0x80 0x01 | 128 | 用 2 个字节 |
3.2 🔷 Variable Header(可变报头)
不同类型报文结构不同,例如:
➤ CONNECT 报文的可变报头包含:
- Protocol Name(MQTT)
- Protocol Level(MQTT 3.1.1 = 4)
- Connect Flags
- Keep Alive
➤ PUBLISH 报文的可变报头包含:
- Topic Name
- Packet Identifier(QOS > 0 时才有)
3.3 🔷 Payload(有效负载)
不同报文的 Payload 内容不同:
CONNECT 报文
- Client ID
- Username(可选)
- Password(可选)
- Will Message(遗嘱消息,可选)
PUBLISH 报文
- Message Body(具体消息内容)
SUBSCRIBE
- Topic Filters(主题过滤)
- QoS 级别
4. MQTT 的三种 QoS 级别(依赖 TCP)
MQTT 之所以在 TCP 之上,部分原因是 QoS 功能依赖可靠传输。
| QoS | 说明 | 对应报文流程 |
|---|---|---|
| 0 | At most once(最多一次) | 无确认 |
| 1 | At least once(至少一次) | PUBACK |
| 2 | Exactly once(仅一次) | PUBREC → PUBREL → PUBCOMP |
QoS2 是一个四步握手,确保消息不重复不丢失。
5. MQTT 的工作流程(TCP 上层逻辑)
1)建立 TCP 连接:
客户端 → Broker
TCP 三次握手2)发送 CONNECT 报文:
Client → Broker:CONNECT
Broker → Client:CONNACK3)SUBSCRIBE 或 PUBLISH
Client → Broker:SUBSCRIBE
Broker → Client:SUBACK
Client → Broker:PUBLISH
Broker → Client:xxx (ACK depending on QoS)4)保持心跳:
Client → Broker:PINGREQ
Broker → Client:PINGRESP5)关闭连接:
Client → Broker:DISCONNECT或者网络断开由 TCP 关闭。
6. MQTT 报文示意图(基于 TCP)
TCP Payload:
┌──────────────┬────────────────┬─────────────────────────┐
│ Fixed Header │ Variable Header│ Payload │
└──────────────┴────────────────┴─────────────────────────┘