MQTT 协议介绍

更新时间:
2023-08-09
下载文档

MQTT 协议介绍

本章将介绍 MQTT 协议。

MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(Publish/Subscribe)模式的轻量级通信协议,该协议构建于 TCP/IP 协议上,由 IBM 在 1999 年发布。MQTT 最大优点在于,可以以极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务。作为一种低开销、低带宽占用的即时通信协议,其在物联网、小型设备、移动应用等方面有较广泛的应用。

MQTT 协议的主要特点:轻巧高效、可靠的消息传递、双向通信、支持不可靠的网络、可启用安全、可扩展到数以百万计的事物。

MQTT 架构

MQTT 是基于发布/订阅(Publish/Subscribe)模式来进行通信及数据交换的,与 HTTP 的请求/响应(Request/Response)模式有本质的不同,MQTT 网络架构由消息服务器(Broker)、订阅者(Subscriber)、发布者(Publisher)组成,订阅者(Subscriber)和发布者(Publisher)都是 MQTT 客户端(Client):

avatar

订阅者(Subscriber)会向消息服务器(Broker)订阅一个主题(Topic)。成功订阅后,Broker 会将该主题下的消息转发给所有的订阅者。

发布者(Publisher)向消息服务器(Broker)发布特定主题(Topic)的消息。

主题(Topic)以 / 为分隔符区分不同的层级。包含通配符 +# 的主题又称为主题过滤器(Topic Filters),不含通配符的称为主题名(Topic Names),例如:

sensor/1/temperature

sensor/1/#

sensor/+/temperature

MQTT 协议

如果您对 MQTT 协议感兴趣,建议到 MQTT 组织官网open in new window 作进一步了解,同时我们为您分享《MQTT 协议中文版》open in new window

MQTT 消息

MQTT 的消息类型如下表所示:

报文类型字段值数据方向描述
保留0禁用保留
CONNECT1Client ---> BrokerClient 连接到 Broker
CONNACK2Broker ---> Client连接确认
PUBLISH3Client <--> Broker发布消息
PUBACK4Client <--> Broker发布确认
PUBREC5Client <--> Broker消息已接收(QoS2 第一阶段)
PUBREL6Client <--> Broker消息释放(QoS2 第二阶段)
PUBCOMP7Client <--> Broker发布结束(QoS2 第三阶段)
SUBSCRIBE8Client ---> BrokerClient 订阅请求
SUBACK9Broker ---> ClientBroker 订阅确认
UNSUBACRIBE10Client ---> BrokerClient 取消订阅
UNSUBACK11Broker ---> ClientBroker 取消订阅确认
PINGREQ12Client ---> BrokerClient 发送心跳
PINGRESP13Broker ---> ClientBroker 回复心跳
DISCONNECT14Client ---> BrokerClient 断开连接请求
保留15禁用保留

连接建立

CONNECT 是 Client 第一条发送的消息。 Client 和 Broker 建立 TCP 链接之后,应立即发送 CONNECT 消息。如果一段时间内 Client 没有向 Broker 发送 CONNECT 消息,那么 Broker 应断开这个链接。 Broker 在收到 CONNECT 消息之后,应回复 CONNACK 消息。CONNACK 消息包含了链接是否成功建立,或者为什么没有建立成功。

CONNECT 消息的 payload 包括:

  • Keep Alive 数值
  • 遗嘱消息 Will 的 Topic
  • 遗嘱消息 Will 的内容
  • Broker 的用户名
  • Broker 的密码

消息 QoS

QoS 标识消息的服务级别,MQTT 规定了三种消息服务级别:

  • QoS 0:消息最多传递一次,如果 Receiver 不可用,则会丢失该消息
  • QoS 1:消息传递至少一次
  • QoS 2:消息仅传送一次

QoS 0 是一种“fire and forget”的消息发送模式:Sender(可能是 Publisher 或者 Broker)发送一条消息之后,就不再关心它有没有发送到对方,也不设置任何重发机制。

QoS 1 包含了简单的重发机制,Sender 发送消息之后等待接收者的 ACK,如果没收到 ACK 则重新发送消息。这种模式能保证消息至少能到达一次,但无法保证消息不重复。

QoS 2 是最高的级别,QoS 2 设计了重发和重复消息发现机制,它需要经过两次通信才能完成:PUBLISH <-> PUBREC,PUBREL <-> PUBCOMP,保证消息到达对方并且严格只到达一次。

实际应用中需要根据应用的特点选择不同的服务级别。

avatar

Retain 消息

如果 Client 发送了一条 Retain 标识为 1 的消息,则 Broker 必须保存这条消息以及它的 QoS。当这条消息的 Topic 有新的订阅者订阅时, Broker 就会把这条消息推送给它。使用 Retain 的好处就是新的订阅者订阅成功之后便能收到最近的一条消息,而无需等待到下一次消息产生时。

每条 Retain 消息都会覆盖上一条,把这条消息变为最新保留消息。

如果 Broker 收到一条 Retain 为 1,但 payload 为空的消息,Broker 会把这个 Topic 保留的 Retain 消息删除。

遗嘱消息 Will

遗嘱消息 Will 都是发生在 Broker 认为 Client 与自己断开了链接。遗嘱消息的存在意义就是能够让其它 Client 及时地知道当前链接已经下线。

以下情况下,Broker 会发布遗嘱消息:

  • Broker 检测到了一个 I/O 错误或者网络故障
  • Client 在保持连接(Keep Alive)的时间内未能通信
  • Client 没有先发送 DISCONNECT 报文直接关闭了网络连接
  • 由于协议错误,Broker 关闭了网络连接

遗嘱消息 Will 包含三部分

  • Flag:是否在意外断开时发布遗嘱消息
  • QoS:遗嘱消息的服务等级
  • Retain:是否保留

Keep Alive

MQTT 协议是基于 TCP 的一个应用层协议,理论上 TCP 协议在丢失连接时会通知上层应用,但是 TCP 有一个半打开连接的问题(half-open connection),在这种状态下,一端的 TCP 连接已经失效,但另外一端并不知情,它认为连接依然是打开的,它需要很长的时间才能感知到对端连接已经断开了,这种情况在使用移动或者卫星网络的时候尤为常见。

所以,仅仅依赖 TCP 层的连接状态监测是不够的,于是 MQTT 协议设计了一套 Keep Alive 机制。在建立连接的时候,可以传递一个 Keep Alive 参数,它的单位为秒,MQTT 协议中约定:在 1.5 * Keep Alive 的时间间隔内,如果 Broker 没有收到来自 Client 的任何数据包,那么 Broker 认为它和 Client 之间的连接已经断开;同样地,如果 Client 没有收到来自 Broker 的任何数据包,那么 Client 认为它和 Broker 之间的连接已经断开。

MQTT 协议设计有一对 PINGREQ/PINGRESP 数据包,当 Broker 和 Client 之间没有任何数据包需要传输的时候,可以通过 PINGREQ/PINGRESP 来满足 Keep Alive 的约定和侦测连接状态。

EdgerOS 对 MQTT 支持

EdgerOS MQTT Broker

EdgerOS 内建了一个 MQTT Broker,可以在 EdgerOS 的设备 App 中启用 MQTT Broker:

avatar

点击设置可进入 MQTT Broker 的详细设置:

avatar

EdgerOS MQTT Client 模块

EdgerOS 也实现了一个 MQTT Client 模块,EdgerOS 应用开发者可以使用该模块,与其它 MQTT Client 设备进行通信:

avatar

MQTT 设备开发

MQTT Client 库

在物联网设备上运行 MQTT 协议,需要实现 MQTT Client 功能,开发时一般采用成熟的 MQTT Client 库。在 MQTT 组织官网open in new window 展示了一些 MQTT Client 库,下图展示了设备相关的、C 和 C++ 语言的 MQTT Client 库:

avatar

MS-RTOS 的 MQTT Client 库

在 MS-RTOS 的 开源社区open in new window 提供了以下三个 MQTT Client 库的移植:

avatar

推荐使用 EPL and EDL 开源协议的 paho-mqtt-embedded-c 工程。

FreeRTOS 的 MQTT Client 库

FreeRTOS 官方提供了一个 MQTT Client 库:

coreMQTTopen in new window

avatar

ESP8266 SDK 的 MQTT Client 库

乐鑫科技官方提供了一个 ESP8266 的 MQTT Client 库:

esp-mqttopen in new window

同时,在乐鑫科技官方提供的 ESP8266_RTOS_SDK 中也有它的集成:

avatar

我们将在《IoT Pi MQTT 设备开发》章节介绍如何开发一个能接入到 EdgerOS 的 MQTT 物联网设备。

文档内容是否对您有所帮助?
有帮助
没帮助