MQTT物联网通信协议
部署MQTT Broker
docker run -d --name emqx-ee \
-p 1883:1883 -p 8081:8081 \
-p 8083:8083 -p 8883:8883 \
-p 8084:8084 -p 18083:18083 \
emqx/emqx-ee:latest
访问web控制台:http://192.168.200.154:18083
默认用户名/密码:admin/public
# 用户密码管理
docker exec -it emqx-ee /bin/bash
./bin/emqx_ctl admins add <Username> <Password> <Tags> # Add dashboard user
./bin/emqx_ctl admins passwd <Username> <Password> # Reset dashboard user password
./bin/emqx_ctl admins del <Username> # Delete dashboard user
部署MQTT Web Client
docker pull emqx/mqttx-web:latest
docker run -d --name mqttx-web -p 80:80 emqx/mqttx-web:latest
MQTT客户端命令行工具mqttx
mqttx <command> [options]
核心命令包括:pub(发布消息)、sub(订阅主题)、conn(测试连接)等。
1. 发布消息(pub)
向指定主题发布消息。
基础用法:
# 向主题 "test" 发布消息 "hello mqtt"
mqttx pub -t "test" -m "hello mqtt" -h "broker.emqx.io" -p 1883
常用参数:
-t, --topic:指定主题(必填)-m, --message:消息内容(必填)-h, --host:MQTT 服务器地址(默认:localhost)-p, --port:端口(默认:1883)-q, --qos:QoS 等级(0/1/2,默认:0)-r, --retain:是否为保留消息(默认:false)-u, --username:用户名-P, --password:密码--client-id:客户端 ID(默认自动生成)--protocol:协议版本(mqttv3.1.1或mqttv5,默认:mqttv3.1.1)
示例(带认证和 QoS 1):
mqttx pub -t "device/temp" -m '{"temp": 25}' -h "emqx-enterprise" -p 1883 -u "user1" -P "pass123" -q 1
2. 订阅主题(sub)
订阅指定主题并接收消息。
基础用法:
# 订阅主题 "test"
mqttx sub -t "test" -h "broker.emqx.io" -p 1883
常用参数(部分同 pub,新增):
-t, --topic:可重复指定多个主题(如-t "test1" -t "test2")-v, --verbose:显示详细信息(包括消息来源、QoS 等)--csv:以 CSV 格式输出消息
示例(订阅多个主题并显示详情):
mqttx sub -t "device/#" -t "sensor/+" -h "localhost" -v
3. 测试连接(conn)
检查与 MQTT 服务器的连接是否正常。
用法:
# 测试连接到指定服务器
mqttx conn -h "broker.emqx.io" -p 1883 -u "test" -P "test"
成功会返回 Connected,失败则显示错误原因(如认证失败、网络不通)。
4. 其他实用命令
-
生成客户端 ID:
mqttx utils clientid # 生成随机客户端 ID -
查看版本:
mqttx --version -
帮助信息:
mqttx --help # 全局帮助 mqttx pub --help # 特定命令帮助
5.高级用法示例
-
使用 MQTT 5.0 协议发布消息:
mqttx pub -t "mqtt5/test" -m "hello mqtt5" --protocol mqttv5 -h "localhost" -p 1883 -
发布 JSON 格式消息并保留:
mqttx pub -t "config" -m '{"max": 100, "min": 0}' -r true -h "broker.emqx.io" -
持续订阅并将消息保存到文件:
mqttx sub -t "logs/#" -h "localhost" > mqtt_logs.txt # 输出重定向到文件
MQTT 协议格式
MQTT 协议的核心是控制报文(Control Packet),所有通信均通过交换控制报文完成。一个完整的 MQTT 控制报文由固定报头(Fixed Header)、可变报头(Variable Header,可选) 和有效载荷(Payload,可选) 三部分组成,结构如下:
+-------------------+-------------------+-------------------+
| 固定报头 (必选) | 可变报头 (可选) | 有效载荷 (可选) |
+-------------------+-------------------+-------------------+
1. 固定报头(Fixed Header)
所有 MQTT 控制报文都必须包含固定报头,用于标识报文类型、QoS 等级、是否保留等核心属性,共2 字节(基础结构),部分报文会扩展更多字节(如剩余长度字段)。
第 1 字节:控制报文类型与标志位
第 1 字节分为高 4 位(D7-D4)和低 4 位(D3-D0):
- 高 4 位(控制报文类型):标识报文的用途,共 14 种类型(0-15 中,15 为保留),常见类型如下:
| 类型值 | 报文类型 | 用途说明 |
|---|---|---|
| 1 | CONNECT | 客户端向服务端发起连接请求 |
| 2 | CONNACK | 服务端向客户端回复连接确认 |
| 3 | PUBLISH | 客户端 / 服务端发布消息(核心报文) |
| 4 | PUBACK | 对 QoS 1 的 PUBLISH 报文的确认 |
| 5 | PUBREC | 对 QoS 2 的 PUBLISH 报文的 “接收确认” |
| 6 | PUBREL | 对 QoS 2 的 PUBREC 报文的 “释放确认” |
| 7 | PUBCOMP | 对 QoS 2 的 PUBREL 报文的 “完成确认” |
| 8 | SUBSCRIBE | 客户端向服务端发起订阅请求 |
| 9 | SUBACK | 服务端向客户端回复订阅确认 |
| 10 | UNSUBSCRIBE | 客户端向服务端发起取消订阅请求 |
| 11 | UNSUBACK | 服务端向客户端回复取消订阅确认 |
| 12 | PINGREQ | 客户端向服务端发送 “心跳”,检测连接状态 |
| 13 | PINGRESP | 服务端向客户端回复心跳确认 |
| 14 | DISCONNECT | 客户端 / 服务端主动断开连接 |
-
低 4 位(标志位)
:不同报文类型的标志位含义不同,仅部分标志位有效(无效位必须设为 0),核心标志位如下:
D3(Retain):仅用于 PUBLISH 报文。若为 1,服务端会保留该消息,后续新订阅该主题的客户端会立即收到这条保留消息;若为 0,服务端不保留,仅推送给当前订阅者。D2-D1(QoS):仅用于 PUBLISH、SUBSCRIBE 等报文,标识消息的 QoS 等级(00=QoS 0,01=QoS 1,10=QoS 2,11 = 保留)。D0(Dup):“重发标志”,仅用于 PUBLISH 报文。若为 1,标识该消息是重发的(因未收到前一次的确认);若为 0,标识是首次发送。
第 2 字节起:剩余长度(Remaining Length)
表示 “可变报头 + 有效载荷” 的总字节数,采用可变长度编码(1-4 字节),目的是减少报头开销(短消息无需占用 4 字节)。
编码规则:每个字节的最高位(D7)为 “延续位”,若为 1,表示后续还有字节;低 7 位(D6-D0)为实际数值。例如:
- 若剩余长度≤127,用 1 字节表示(
D7=0,低 7 位为数值); - 若剩余长度 > 127,
D7=1,低 7 位表示 “数值的低 7 位”,后续字节继续补充高位,最多 4 字节(最大可表示 4,294,967,295 字节)。
2. 可变报头(Variable Header)
并非所有报文都有可变报头,仅特定类型(如 CONNECT、PUBLISH、SUBSCRIBE)需要,用于携带该报文的 “附加属性”。常见可变报头内容:
- CONNECT 报文:包含 “协议名(MQTT)”、“协议级别(如 5=MQTT 5.0,4=MQTT 3.1.1)”、“连接标志(如是否需要用户名 / 密码、是否清理会话)”、“保持连接(Keep Alive)时间”。
- PUBLISH 报文:包含 “主题名(Topic Name)”—— 用于标识消息的 “目的地”,客户端通过订阅主题接收消息;若 QoS≥1,还包含 “报文标识符(Packet Identifier)”(2 字节,唯一标识该消息,用于确认和重发)。
- SUBSCRIBE/SUBACK 报文:包含 “报文标识符”(用于匹配订阅请求与确认)。
3. 有效载荷(Payload)
也称为 “消息体”,仅特定报文需要,用于携带实际数据。常见有效载荷内容:
- CONNECT 报文:包含 “客户端标识符(Client ID,唯一标识客户端)”、“用户名(可选)”、“密码(可选)”。
- PUBLISH 报文:包含 “业务数据”(如传感器采集的温度、设备状态等,可二进制或文本格式)。
- SUBSCRIBE 报文:包含 “订阅列表”(主题过滤器 + 期望的 QoS 等级,如
sensor/temp+ QoS 1)。
MQTT QoS 三个等级
QoS(Quality of Service,服务质量)是 MQTT 的核心特性,用于在 “网络不稳定” 场景下保证消息的 “传递可靠性”,同时平衡 “可靠性” 与 “开销”(QoS 越高,通信步骤越多,带宽 / 资源消耗越大)。三个等级的核心差异是 “消息传递的确认机制” 和 “可靠性保证”。
1. QoS 0:最多一次(At Most Once)
-
核心定义:消息 “最多传递一次”,可能丢失,但不会重复。
类比:“发短信后不等对方回复”—— 对方可能收到,也可能没收到(如网络断连),但不会收到多条相同消息。 -
通信流程:1 步完成(无确认)
发送方(客户端 / 服务端)→ 直接发送 PUBLISH 报文(Dup=0,QoS=00)→ 不等待确认,发送即结束。 -
适用场景
对消息可靠性要求低、允许丢失的场景,如:
- 传感器实时采集的 “非关键数据”(如实时温度,丢一条不影响整体分析);
- 设备周期性上报的 “状态心跳”(如设备在线状态,下一次上报会覆盖)。
-
优缺点:
✅ 优点:开销最小(无确认、无重发),适合带宽 / 资源受限的设备(如低功耗传感器);
❌ 缺点:消息可能丢失(如网络中断时)。
2. QoS 1:至少一次(At Least Once)
-
核心定义:消息 “至少传递一次”,确保不丢失,但可能重复。
类比:“发短信后等对方回复‘收到’,没收到就重发”—— 对方一定会收到(可能收到多次,需业务层去重)。 -
通信流程
:2 步完成(“发送 - 确认”)
- 发送方发送 PUBLISH 报文(Dup=0,QoS=01,带报文标识符);
- 接收方收到后,立即处理消息,并回复PUBACK 报文(携带相同的报文标识符);
- 发送方若在 “超时时间” 内未收到 PUBACK,会重发 PUBLISH 报文(Dup=1),直到收到确认。
-
适用场景
对消息 “不丢失” 有要求,但可接受重复的场景,如:
- 设备控制指令(如 “开灯”,重复执行一次不影响);
- 物联网设备上报的 “关键数据”(如电表读数,重复读数可通过时间戳去重)。
-
优缺点:
✅ 优点:确保消息不丢失,可靠性高于 QoS 0;
❌ 缺点:可能重复(需业务层处理去重),开销高于 QoS 0(多一次确认)。
3. QoS 2:恰好一次(Exactly Once)
-
核心定义:消息 “恰好传递一次”,确保不丢失、不重复,是最高可靠性等级。
类比:“发短信后,对方先回复‘已收到,待处理’,我方回复‘请处理’,对方处理后回复‘已处理’”—— 全程闭环,确保对方只处理一次。 -
通信流程
:4 步完成(“接收确认 - 释放确认”)
- 发送方发送 PUBLISH 报文(Dup=0,QoS=10,带报文标识符);
- 接收方收到后,暂存消息(不立即处理),并回复PUBREC 报文(确认 “已接收”,携带相同标识符);
- 发送方收到 PUBREC 后,停止重发 PUBLISH,发送PUBREL 报文(确认 “可释放并处理消息”,标识符不变);
- 接收方收到 PUBREL 后,处理暂存的消息,并回复PUBCOMP 报文(确认 “已处理完成”);
- 发送方收到 PUBCOMP 后,流程结束;若超时未收到,重发 PUBREL(而非 PUBLISH)。
-
适用场景
对消息 “不丢失、不重复” 有严格要求的场景,如:
- 金融交易数据(如物联网支付、设备计费);
- 医疗设备指令(如远程手术设备控制,重复执行可能引发风险)。
-
优缺点:
✅ 优点:最高可靠性,确保消息仅被处理一次;
❌ 缺点:开销最大(4 步通信、需暂存消息),不适合带宽 / 资源极度受限的设备。
QoS 三个等级对比表
| 特性 | QoS 0(最多一次) | QoS 1(至少一次) | QoS 2(恰好一次) |
|---|---|---|---|
| 可靠性保证 | 可能丢失,不重复 | 不丢失,可能重复 | 不丢失,不重复 |
| 通信步骤 | 1 步(无确认) | 2 步(PUBLISH→PUBACK) | 4 步(PUBLISH→PUBREC→PUBREL→PUBCOMP) |
| 报文标识符 | 不需要 | 需要(用于确认) | 需要(用于多步确认) |
| 消息暂存 | 不需要 | 发送方暂存(待确认) | 发送方 + 接收方均暂存 |
| 带宽 / 资源消耗 | 最低 | 中等 | 最高 |
| 典型应用场景 | 实时传感器数据、心跳 | 设备控制指令、关键上报 | 金融交易、医疗指令 |
关键补充说明
- QoS 等级的协商:客户端订阅主题时会指定 “期望的 QoS”,服务端会根据自身能力(如是否支持该 QoS)返回 “实际的 QoS”(≤期望 QoS),最终以服务端确认的 QoS 为准。
- MQTT 版本差异:MQTT 5.0 在 3.1.1 的基础上扩展了 QoS 的 “属性”(如消息过期时间、延迟发布),但核心的三个 QoS 等级定义完全一致。
- 服务端角色:QoS 的实现依赖服务端的 “转发逻辑”—— 例如,客户端 A 以 QoS 1 发布消息到服务端,服务端会以 QoS 1 将消息转发给订阅的客户端 B,并分别与 A、B 完成 QoS 1 的确认流程。
主题(Topic)
主题是 MQTT 中用于定位消息流向的分层字符串,相当于消息的 “邮箱地址”—— 发布者(Publisher)向指定主题 “投递” 消息,订阅者(Subscriber)通过订阅主题 “接收” 对应消息。主题本身不存储消息,仅作为 “路由标签”。
主题的结构规则
-
分层分隔符
使用
/分割主题的不同层级,形成树形结构(类似文件系统路径),例如:sensor/temperature/room1(1 号房间的温度传感器)device/light/livingroom(客厅的灯光设备)
-
通配符支持
订阅者可通过通配符订阅多个关联主题(发布者不能使用通配符发布消息),分为两种:
单层通配符(+):匹配单个层级的任意字符(不能匹配多层或末尾无
/的主题)多层通配符(#):匹配当前层级及以下所有层级(必须作为主题的最后一个字符)
通配符类型 符号 示例 匹配结果 单层通配符 +sensor/+/room1匹配 sensor/temperature/room1、sensor/humidity/room1;不匹配sensor/temperature/room1/window多层通配符 #sensor/temperature/#匹配 sensor/temperature/room1、sensor/temperature/room2/window、sensor/temperature(单层主题) -
禁止特殊字符:不能包含
\0(空字符),避免使用空格、#(非末尾)、+(非层级分隔)等,防止路由异常。 -
大小写敏感:
Sensor/Temperature与sensor/temperature是两个不同主题。
主题的常见设计范式
主题设计需兼顾 “灵活性” 与 “可维护性”,推荐按 “业务域 / 设备类型 / 设备 ID / 数据类型” 分层,例如:
- 设备状态上报:
device/{deviceType}/{deviceID}/state(如device/light/12345/state) - 控制指令下发:
device/{deviceType}/{deviceID}/command(如device/fan/67890/command) - 全局广播:
broadcast/all/notice(所有设备订阅此主题接收通知)
消息(Message)
消息是 MQTT 中传递的实际数据内容,由 “有效载荷(Payload)” 和 “消息属性(Header)” 两部分组成,设计上遵循 “轻量优先” 原则,最小可仅包含 1 字节数据。
消息的核心组成
| 组成部分 | 说明 | 示例 |
|---|---|---|
| 有效载荷(Payload) | 实际传递的业务数据,格式由业务自定义(如 JSON、二进制、文本) | 温度数据:{"temp":25.3,"time":"2024-05-20 14:30"} |
| 消息属性(Header) | 控制消息传输行为的元数据,核心属性包括: - QoS 等级:消息传递的可靠性级别 - Retain 标志:是否在 Broker 端保留最新消息 - Duplicate 标志:是否为重复发送的消息 | QoS=1,Retain=1(保留最新温度值) |
关键消息属性详解
- QoS(Quality of Service)等级:MQTT 的核心可靠性机制,定义了 “发布者→Broker→订阅者” 的消息传递保障。
- Retain 标志:控制 Broker 是否 “缓存” 主题的最新消息。当 Retain=1 时,Broker 会存储该主题的最新消息;新订阅者订阅此主题时,会直接收到 Broker 缓存的最新消息(无需等待发布者再次发送)。
示例:传感器每小时上报一次温度,设置 Retain=1 后,新接入的监控平台订阅温度主题时,会立即获取上一次的温度值,无需等待 1 小时。 - Duplicate(Dup)标志:仅在 QoS 1/2 中生效,标识该消息是否为 “重发消息”(如 QoS 1 中发布者未收到 PUBACK 而重发),帮助订阅者过滤重复数据。
订阅(Subscription)
订阅是订阅者(如物联网网关、手机 APP、云平台)向 MQTT Broker(消息代理服务器)发起的 “消息接收请求”—— 订阅者通过指定 “主题(含通配符)” 和 “QoS 等级”,告知 Broker:“我需要接收该主题下,QoS 不超过 X 的所有消息”。
订阅的核心机制
- 订阅流程:订阅者→Broker 发送
SUBSCRIBE请求(携带主题和订阅 QoS)→Broker 验证通过后返回SUBACK确认→订阅生效,后续该主题的消息会被 Broker 主动推送给订阅者。 - 订阅 QoS 与消息 QoS 的关系:订阅者设置的 QoS 是 “最大接收等级”,实际接收的消息 QoS 取 “发布者 QoS” 和 “订阅 QoS” 的较小值。
示例:发布者以 QoS 2 发布消息,订阅者以 QoS 1 订阅,则订阅者最终接收的消息 QoS 为 1(Broker 自动降级)。
订阅的实践要点
- 取消订阅:订阅者可通过发送
UNSUBSCRIBE请求取消订阅,Broker 返回UNSUBACK确认后,不再推送该主题的消息。 - 多订阅者共享主题:同一主题可被多个订阅者订阅,Broker 会将消息复制并推送给所有订阅者(Pub/Sub 模式的核心特性,实现 “一对多” 通信)。
示例:3 个手机 APP 同时订阅device/light/livingroom/state,当灯光状态变化时,3 个 APP 会同时收到状态更新消息。 - 订阅权限控制:部分 Broker(如 EMQX、Mosquitto)支持 ACL(访问控制列表),可限制订阅者仅能订阅指定主题(如禁止设备订阅
broadcast/all全局主题),保障安全性。

浙公网安备 33010602011771号