MQTT 协议

2025年3月17日 | 阅读 8 分钟

MQTT 代表消息队列遥测传输。MQTT 是一种机器到机器的物联网连接协议。它是一种极轻量级的发布-订阅消息传输协议。该协议适用于连接带宽有限的远程位置。这些特性使其在各种情况下都非常有用,包括需要稳定环境的场景,例如机器到机器通信和物联网上下文。它是一个发布和订阅系统,我们可以在其中作为客户端发布和接收消息。它使得多个设备之间的通信变得容易。它是一个简单的消息协议,专为资源受限设备和低带宽设计,因此它是物联网应用的理想解决方案。

MQTT 的特点

MQTT 具有一些在其他协议中很少见的独特功能。MQTT 的一些特性如下所示:

  • 它是一种机器到机器协议,即它提供了设备之间的通信。
  • 它被设计成一个简单轻量级的消息协议,使用发布/订阅系统在客户端和服务器之间交换信息。
  • 它不需要客户端和服务器同时建立连接。
  • 它提供更快的 数据传输,就像 WhatsApp/Messenger 提供快速交付一样。它是一种实时消息协议。
  • 它允许客户端订阅特定主题,以便它们可以接收它们正在寻找的信息。

MQTT 历史

MQTT protocol

MQTT 由 Dr. Andy Stanford-Clark(IBM)和 Arlen Nipper 开发。该协议的先前版本 3.1 和 3.1.1 在 MQTT ORG 下发布。2014 年,MQTT 由 OASIS 正式发布。OASIS 成为 MQTT 开发的新家。然后,OASIS 开始了 MQTT 的进一步开发。版本 3.1.1 与 3.1 向后兼容,仅带来了一些小的改动,例如连接消息的改动以及对 3.1 版本的澄清。最新的 MQTT 版本是 5.0,它是 3.1.1 版本的后续版本。版本 5.0 不像版本 3.1.1 那样向后兼容。根据规范,版本 5.0 具有大量功能,可以改进现有代码。

版本 5.0 的主要功能目标是:

  • 增强可伸缩性和大型系统,以便能够连接数千甚至数百万台设备。
  • 改进错误报告。

MQTT 架构

要理解 MQTT 架构,我们首先要了解 MQTT 的组成部分。

  • 信息
  • 客户
  • 服务器或代理
  • 主题

信息

消息是在网络上传输的数据,供应用程序使用。当消息在网络上传输时,消息包含以下参数:

  1. 有效载荷数据
  2. 服务质量 (QoS)
  3. 属性集合
  4. 主题名称

客户

在 MQTT 中,订阅者和发布者是客户端的两种角色。客户端订阅主题以发布和接收消息。简单来说,我们可以说,如果任何程序或设备使用了 MQTT,那么该设备就称为客户端。当设备打开与服务器的网络连接,发布其他客户端希望看到的消息,订阅它感兴趣的消息,取消订阅它不感兴趣的消息,并关闭与服务器的网络连接时,它就是一个客户端。

在 MQTT 中,客户端执行两个操作:

在 MQTT 中,客户端执行两个操作:

发布:当客户端向服务器发送数据时,我们称此操作为发布。

订阅:当客户端从服务器接收数据时,我们称此操作为订阅。

Server (服务器版)

允许客户端发布消息和订阅消息的设备或程序。服务器接受来自客户端的网络连接,接受来自客户端的消息,处理订阅和取消订阅请求,将应用程序消息转发给客户端,并关闭与客户端的网络连接。

主题

MQTT protocol

用于消息的标签与服务器已知的订阅进行匹配,称为主题。

MQTT 架构

MQTT protocol

现在我们来看看 MQTT 的架构。为了更清楚地理解它,我们将举一个例子。假设一个设备有一个温度传感器,并希望将读数发送到服务器或代理。如果另一端的手机或桌面应用程序希望接收此温度值,那么将会发生两件事。发布者首先定义主题;例如,温度,然后发布消息,即温度值。发布消息后,另一端的手机或桌面应用程序将订阅该主题,即温度,然后接收发布的消息,即温度值。服务器或代理的作用是将发布的消息传递给手机或桌面应用程序。

MQTT 消息格式

MQTT protocol

MQTT 使用命令和命令确认格式,这意味着每个命令都有一个关联的确认。如上图所示,CONNECT 命令有 CONNACK,SUBSCRIBE 命令有 SUBACK,PUBLISH 命令有 PUBACK。这种机制类似于 TCP 协议中的握手机制。

现在我们来看看 MQTT 的数据包结构或消息格式。

MQTT protocol

MQTT 消息格式包含 2 字节的固定头,所有 MQTT 数据包都包含此字段。第二个字段是可变头,并非总是存在。第三个字段是有效载荷,也并非总是存在。有效载荷字段主要包含正在发送的数据。我们可能认为有效载荷是一个强制字段,但并非如此。某些命令不使用有效载荷字段,例如 disconnect 消息。

固定头

让我们观察固定头的格式。

MQTT protocol

正如我们在上面的格式中可以看到的,固定头包含两个字节。第一个字节包含以下字段:

  • MQTT 控制数据包类型:它占用 4 位,即位 7 到 4。这 4 位是指定值,每位代表 MQTT 控制数据包类型。
  • 特定于每个 MQTT 数据包类型的标志:剩余的 4 位代表特定于每个 MQTT 数据包类型的标志。

字节 2 包含剩余长度,这是一个可变长度字节整数。它表示当前控制数据包中剩余的字节数,包括可变头和有效载荷中的数据。因此,我们可以说剩余长度等于可变头和有效载荷中的数据之和。

MQTT 控制数据包类型

MQTT protocol

上表显示了具有 4 位值和方向流的控制数据包类型。我们可以看到每个命令后面都有一个确认,例如 CONNECT 有 CONNACK,PUBLISH 有 PUBACK、PUBREC、PUBREL 和 PUBCOMP,SUBSCRIBE 有 SUBACK,UNSUBSCRIBE 有 UNSUBACK。

标志位

MQTT protocol

上表显示了与每个命令关联的标志值。此处,保留表示将来使用,这意味着它目前未被使用。对于 PUBLISH 命令,标志位进一步分为 DUP、QoS 和 RETAIN,其中 DUP 是 PUBLISH 数据包的重复传输,QoS 是服务质量,RETAIN 是保留消息标志。

剩余长度

剩余长度是一个可变长度整数,表示当前控制数据包中剩余的字节数,包括可变头和有效载荷中的数据。因此,剩余长度等于可变头中的数据加上有效载荷。

剩余长度 = 可变头长度 + 有效载荷长度

例如,如果可变头的长度是 20,有效载荷的长度是 30,那么剩余长度就是 50。

剩余长度最多可以使用 4 个字节,从 2 个字节开始,最多可以使用 4 个字节。

此字段使用 7 位表示长度,MSB 位可用于继续标志。如果继续标志为 1,则下一个字节也是剩余长度的一部分。

如果继续标志为 0,则该字节是剩余长度的最后一个字节。

可变头

某些类型的 MQTT 控制数据包包含一个可选字段,即可变头组件。此字段位于固定头和有效载荷之间。可变头的内容取决于数据包类型。可变头包含数据包标识符字段,该字段在多个数据包类型中是通用的。许多 MQTT 控制数据包类型的可变头组件包含一个 2 字节的整数,即数据包标识符字段。

下面给出的列表包含数据包标识符字段:

  • PUBLISH
  • PUBACK
  • PUBREC
  • PUBREL
  • PUBCOMP
  • SUBSCRIBE
  • SUBACK
  • UNSUBSCRIBE
  • UNSUBACK

与数据包标识符字段相关的要点:

  • 如果 QoS(服务质量)的值设置为零,则 PUBLISH 数据包不应包含数据包标识符字段。这意味着,如果 QoS 的值大于零,则只有 PUBLISH 数据包才会包含数据包标识符字段。
  • 当客户端发送新的 SUBSCRIBE、UNSUBSCRIBE 或 PUBLISH MQTT 控制数据包时,它应该分配一个当前未使用的非零数据包标识符。
  • 当服务器发送新的 PUBLISH MQTT 控制数据包时,它应该分配一个当前未使用的非零数据包标识符。
  • PUBACK、PUBREC、PUBUREL、PUBREC 是 PUBLISH 命令的确认数据包,它们包含与 PUBLISH 数据包相同的标识符。
  • SUBACK 和 UNSUBACK 分别是 SUBSCRIBE 和 UNSUBSCRIBE 的确认数据包。这两个数据包(SUBACK 和 UNSUBACK)都使用与 SUBSCRIBE 和 UNSUBSCRIBE 数据包相同的标识符。
  • 数据包标识符在处理相应的确认数据包后可以重复使用。其定义如下:

如果 QoS 的值为 1,则 PUBLISH 的确认数据包为 PUBACK。如果处理了 PUBACK,则 PUBACK 的数据包标识符可以重用。

如果 QoS 的值为 2,则 PUBLISH 的确认数据包将是 PUBCOMP 或 PUBREC。

载荷

在 ICMP 消息格式中,最后一个 MQTT 控制数据包是有效载荷。此字段包含要发送的数据。例如,在 CONNECT 数据包的情况下,有效载荷是客户端 ID、用户名和密码;在 PUBLISH 数据包的情况下,有效载荷只是应用程序消息。

MQTT protocol
下一个主题计算机网络教程