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.1mqttv5,默认: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.高级用法示例
  1. 使用 MQTT 5.0 协议发布消息

    mqttx pub -t "mqtt5/test" -m "hello mqtt5" --protocol mqttv5 -h "localhost" -p 1883
    
  2. 发布 JSON 格式消息并保留

    mqttx pub -t "config" -m '{"max": 100, "min": 0}' -r true -h "broker.emqx.io"
    
  3. 持续订阅并将消息保存到文件

    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 步完成(“发送 - 确认”)

    1. 发送方发送 PUBLISH 报文(Dup=0,QoS=01,带报文标识符);
    2. 接收方收到后,立即处理消息,并回复PUBACK 报文(携带相同的报文标识符);
    3. 发送方若在 “超时时间” 内未收到 PUBACK,会重发 PUBLISH 报文(Dup=1),直到收到确认。
  • 适用场景

    对消息 “不丢失” 有要求,但可接受重复的场景,如:

    • 设备控制指令(如 “开灯”,重复执行一次不影响);
    • 物联网设备上报的 “关键数据”(如电表读数,重复读数可通过时间戳去重)。
  • 优缺点
    ✅ 优点:确保消息不丢失,可靠性高于 QoS 0;
    ❌ 缺点:可能重复(需业务层处理去重),开销高于 QoS 0(多一次确认)。

3. QoS 2:恰好一次(Exactly Once)
  • 核心定义:消息 “恰好传递一次”,确保不丢失、不重复,是最高可靠性等级。
    类比:“发短信后,对方先回复‘已收到,待处理’,我方回复‘请处理’,对方处理后回复‘已处理’”—— 全程闭环,确保对方只处理一次。

  • 通信流程

    :4 步完成(“接收确认 - 释放确认”)

    1. 发送方发送 PUBLISH 报文(Dup=0,QoS=10,带报文标识符);
    2. 接收方收到后,暂存消息(不立即处理),并回复PUBREC 报文(确认 “已接收”,携带相同标识符);
    3. 发送方收到 PUBREC 后,停止重发 PUBLISH,发送PUBREL 报文(确认 “可释放并处理消息”,标识符不变);
    4. 接收方收到 PUBREL 后,处理暂存的消息,并回复PUBCOMP 报文(确认 “已处理完成”);
    5. 发送方收到 PUBCOMP 后,流程结束;若超时未收到,重发 PUBREL(而非 PUBLISH)。
  • 适用场景

    对消息 “不丢失、不重复” 有严格要求的场景,如:

    • 金融交易数据(如物联网支付、设备计费);
    • 医疗设备指令(如远程手术设备控制,重复执行可能引发风险)。
  • 优缺点
    ✅ 优点:最高可靠性,确保消息仅被处理一次;
    ❌ 缺点:开销最大(4 步通信、需暂存消息),不适合带宽 / 资源极度受限的设备。

QoS 三个等级对比表
特性 QoS 0(最多一次) QoS 1(至少一次) QoS 2(恰好一次)
可靠性保证 可能丢失,不重复 不丢失,可能重复 不丢失,不重复
通信步骤 1 步(无确认) 2 步(PUBLISH→PUBACK) 4 步(PUBLISH→PUBREC→PUBREL→PUBCOMP)
报文标识符 不需要 需要(用于确认) 需要(用于多步确认)
消息暂存 不需要 发送方暂存(待确认) 发送方 + 接收方均暂存
带宽 / 资源消耗 最低 中等 最高
典型应用场景 实时传感器数据、心跳 设备控制指令、关键上报 金融交易、医疗指令
关键补充说明
  1. QoS 等级的协商:客户端订阅主题时会指定 “期望的 QoS”,服务端会根据自身能力(如是否支持该 QoS)返回 “实际的 QoS”(≤期望 QoS),最终以服务端确认的 QoS 为准。
  2. MQTT 版本差异:MQTT 5.0 在 3.1.1 的基础上扩展了 QoS 的 “属性”(如消息过期时间、延迟发布),但核心的三个 QoS 等级定义完全一致。
  3. 服务端角色: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/room1sensor/humidity/room1;不匹配 sensor/temperature/room1/window
    多层通配符 # sensor/temperature/# 匹配 sensor/temperature/room1sensor/temperature/room2/windowsensor/temperature(单层主题)
  • 禁止特殊字符:不能包含 \0(空字符),避免使用空格、#(非末尾)、+(非层级分隔)等,防止路由异常。

  • 大小写敏感Sensor/Temperaturesensor/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全局主题),保障安全性。
posted @ 2025-08-27 17:57  wanghongwei-dev  阅读(27)  评论(0)    收藏  举报