Qt MQTT 概述#

深入了解 MQTT 协议和 Qt MQTT 模块。

Qt MQTT 可让您创建可在 MQ 感知传输(MQTT)协议上通信的应用和设备。它完全符合 MQTT 协议规范。

发布和订阅#

MQTT 是一种操作在发布/订阅模型上的机对机连接协议。MQTT 客户端是一个程序或设备,使用 MQTT 在 MQTT 服务器(也称为 代理)上创建网络连接。一旦建立连接,客户端就可以向代理发送消息。其他客户端可以订阅来自客户端的特定主题的通知。

../_images/mqtt.png

例如,如果 Client 2 订阅了 Topic A 上的消息,那么当 Client 1 在该主题上发送消息时,它会收到通知。如果 Client 3 订阅了 Topic ATopic B,那么它会收到关于这两个主题的消息通知。

Qt MQTT 是一个不包含代理的客户端解决方案。它特别适合开发嵌入式设备的遥测应用程序。但是,Qt MQTT 没有外部依赖项,因此可以运行在所有支持的 Qt 平台上。

主题#

主题存储在层次树结构中。标准并未指定如何设计树,也未提供预定义的层次集合。您可以自由设计项目的需求,如下是一个主题层级的例子,其中 active 表示所有 active 传感器,而 housegarage 是单独的传感器。

sensors/active
sensors/house/temperature
sensors/house/bedroom/light
sensors/house/livingroom/light
sensors/garage/temperature
sensors/garage/light

使用通配符订阅主题#

当客户端订阅主题时,它们可以使用井号(#)和加号(+)作为通配符。井号表示客户端希望接收主题及其子主题上的所有消息的通知。例如,如果一个客户端订阅了 sensors/house/#,它将收到 house 传感器上的所有消息。

加号表示在查找匹配的子主题时可以跳过树上的分支。例如,如果一个客户端订阅了 sensors/+/temperature,它将接收到来自任何传感器的关于 temperature 的消息。您可以使用多个加号来跳过多个分支。例如,house/+/+/temperature 可以用于接收来自一个家庭中所有公寓内所有房间的温度消息。

共享订阅#

共享订阅 描述了一组订阅一个主题过滤器的订阅者。并非所有订阅者都会收到消息,只有一位订阅者会收到。这可以支持多个客户端之间的负载均衡。共享订阅的格式是

$share/{sharename}/{topicfilter}

例如,如果 Client 1Client 2 应共享对主题 sensors/house/temperature 的订阅,那么订阅要订阅的主题过滤器的格式是

$share/poolAB/sensors/house/temperature

服务器分发消息的顺序未定义。这是一项服务器特定选项。

要确定服务器是否支持共享订阅,请参阅sharedSubscriptionSupported()

话题别名#

在树形结构中组织话题有助于区分数据通道并提供信息的逻辑顺序。然而,这可能导致在消息发布过程中使用非常长的话题名称,因此增加了每个消息的大小。

MQTT 5.0 协议版本引入了话题别名来解决这个问题。发送的是整数值而不是话题字符串。为了创建客户端和服务器之间初始映射,话题字符串和别名都需要包含在消息中。之后,仅使用带有空话题的 ID。

可以通过使用另一个话题字符串与话题别名来更改此映射。请注意,此映射不一定适用于其他连接,如服务器到其他客户端的连接。每个连接都需要手动创建此映射。

Qt MQTT 提供了一个自动机制来帮助降低数据速率。在 QMqttClient 建立连接后,将存储服务器支持的话题别名信息。随后,在发布消息的顺序中使用话题别名,直到所有可用的别名都使用完毕。用户始终可以通过在发布时使用 setTopicAlias() 来修改此映射。

QMqttClient 订阅话题时,服务器也可以使用话题别名,具体取决于客户端设置的 maximumTopicAlias() 键值。客户端会自动映射话题别名并透明地转发包括完整话题字符串的消息给用户。

安全#

客户端和代理之间的连接通过内置的认证系统进行保护,该系统使用用户名和密码。在传输层使用 SSL/TLS 加密消息。加密 MQTT 消息的标准端口号是 8883。

服务质量#

定义了以下消息服务质量 (QoS) 级别

  • 最多一次(0)表示根据操作环境的最大努力交付消息,因此可能会发生消息丢失。此级别可应用于环境传感器数据,例如,个别读数丢失无关紧要,因为下一个读数将很快发布。

  • 至少一次(1)表示确保消息到达,但可能会出现重复。

  • 精确一次(2)表示确保消息恰好到达一次。此级别可用于账单系统,例如,重复或丢失的消息可能导致错误的计费。

最后遗嘱消息#

遗书(又称遗嘱),是由客户端发送并存放在代理位置的消息。如果客户端和代理之间的连接意外中断,遗书将转发给《Will Topic》(遗书主题)的任何订阅者。

遗书必须在连接阶段指定。因此,在调用connectToHost()connectToHostEncrypted()之前,必须设置它们。一个遗书具有常规消息的所有属性,其中包括遗书主题、QoS级别、保留标志和消息负载。

如果客户端通过调用disconnectFromHost()以常规方式从代理断开连接,代理将丢弃遗书。如果需要,客户端负责在断开连接前发送所有必需的消息。

保留消息#

保留消息存储在代理端。随着未来客户端的连接,它们将接收到这样的消息。一个典型的用例是将发布者的当前健康状况存储在保留消息中。订阅者将立即收到有关状态的消息。

代理只能为特定主题存储最后发送的保留消息。如果一个客户端以QoS级别零发布保留消息,代理そのトピック之前保留的任何先前保留消息必须被丢弃。代理应存储最后一条消息,但也可能丢弃它。这取决于代理的实现。