MQTT客户端发布消息时使用的是PUBLISH报文,发布成功之后会接收到PUBACK报文。

订阅时发送SUBSCRIBE报文,订阅成功会接收到SUBACK报文。

取消订阅发送UNSUBSCIBE报文。

PUBLISH

在MQTT中,客户端在成功连接到代理之后就可以发送消息。

代理根据主题来对消息进行过滤并转发到已订阅的客户端,每条消息都会包含一个主题。

消息的有效负载是以字节为单位的数据,支持各种数据类型,包括文本、数字、图像、二进制数据以及XML或JSON。

报文内容如下图:

PUBLISH报文有以下几个属性,分别是:

PacketID

数据包标识符(PackageID),在MQTT代理和客户端之间唯一标识消息。用于识别特定消息并确保消息按发送顺序传递,仅在QoS>0时有效。

可以使用MQTT客户端库或代理来设置此标识符。

当在QoS>0的消息通信过程中,客户端必须等待来自代理的PUBACK或PUBREC消息,然后才能发送下一条新消息。而PackageID就是用来区分是否是新消息。

PacakgeID对于MQTT的可靠性机制至关重要,有助于确保消息正确有效地传递。

Topic Name

用于指示该条消息发布到哪个主题上,MQTT代理向订阅该主题的客户端传递这条消息。

主题是一个字符串,使用“/”作为分隔符用以分层,为客户端提供订阅消息的方式。

订阅主题可以使用以下两种通配符:

  1. +用于匹配主题层次结构中的单个级别。例如,订阅sensors/+/livingroom将匹配sensors/temperature/livingroomsensors/humidity/livingroom,但不匹配sensors/temperature/kitchen
  2. #用于匹配层次结构中的多个级别。例如,订阅sensors/#将匹配sensors/temperature/livingroomsensors/humidity/kitchensensors/power/meter1

QoS

消息质量等级,QoS有3个等级,分别是:

QoS等级说明
QoS0(最多一次)此级别不保证消息传递成功。发送方仅传递一次消息,无论接收方是否收到,都不在重发。
QoS1(至少一次)此级别确保消息至少传递一次。发送方在收到接收方的确认之前会一直传递消息,可能会导致多次传递。
QoS2(确定一次)此级别为消息传递提供最高级别的保证,确保消息恰好传递一次。发送方在收到接收方的确认之前发送的消息都被认定是重复消息,直到收发双方协商一致之后开启新消息传递。

QoS2比QoS1级别多了一个步骤,收发双方需要相互确认下一条新消息的开始。

Retain Flag

保留标志(Retain)决定是否将消息存储在代理中。

当Retain标志设置1时,无论该消息对应的主题是否被客户端订阅,代理都会存储该消息与对应的主题。

发布消息时,保留标志设置为1的消息称为保留消息,MQTT代理为每个主题仅保留一条消息

当新客户端订阅带有保留消息的主题时,代理会将最新的保留消息(关于该主题)发送给客户端。这将允许客户接收最新的相关信息,即使其以前没有订阅过该主题。

Payload

负载是消息的实际内容,可以包含任何类型的数据。

MQTT可以处理不同的数据类型,包括图像、任何编码的文本、加密数据和二进制数据。

DUP Flag

该标志表示消息是重复的,仅与QoS>0的消息相关。

通常在接收者(客户端或代理)没有发送确认消息的情况下再次发送该消息时设置。

当客户端或代理收到带有DUP标志的消息时,如果之前已经收到具有相同PacketID的消息,则会忽略该消息。如果客户端或代理之前未收到相同PacketID的消息,则正常处理该消息。

MQTT代理如何处理消息

当MQTT代理接收到客户端传递的消息后,为了确保按照客户端指定的QoS级别处理消息,会执行以下步骤:

  1. 消息接收:MQTT代理接收客户端发送的消息,并验证报文头和内容格式。
  2. 消息确认:MQTT代理根据客户端指定的QoS级别,向客户端发送确认消息。
  3. 处理消息:MQTT代理根据客户端发送的消息主题,将该消息传递给订阅了该主题的客户端。并且根据消息的Retain标志,判断是否需要存储在代理中。

发布消息的客户端只关心将PUBLISH消息传递给代理。

一旦代理接收到PUBLISH消息,就有责任将该消息传递给所有订阅者。

发布客户端不会获得任何反馈,以了解是否有人对发布的消息感兴趣,或者有多少客户端收到了来自代理的消息

SUBSCRIBE

收发消息是相辅相成的,如果没有订阅者接收消息,那么发布消息就毫无意义。

当客户端想要订阅消息,就需要向代理发送SUBSCRIBE报文,以告知代理订阅的主题。

SUBSCRIBE报文包含两个字段,分别是数据包标识符(PackageID)和订阅主题列表

字段名说明
PacketIDMQTT代理和客户端之间唯一标识消息,可以使用客户端库或代理进行设置。用于确保客户端识别出与SUBSCRIBE相关联的响应消息。
Topic List客户端想要订阅的一个或多个主题的列表。列表中每条都会包含一个主题和一个QoS级别。

订阅的主题可以包含通配符,

如果一个客户端多次订阅相同主题,MQTT代理仅为该主题提供最高级别的QoS。

当MQTT代理收到来自客户端的带有主题与QoS级别的SUBSCRIBE报文时,将会返回一条带有QoS最大级别的SUBACK报文通知客户端订阅是否成功。

SUBACK

当MQTT客户端向代理发送一条带有主题和QoS级别的SUBSCRIBE报文时,代理就会向客户端响应一条SUBACK报文来确认该订阅请求。

SUBACK报文用于MQTT代理确认收到SUBSCRIBE报文,并指示是否接受或拒绝该订阅请求

交互流程如下图:

sequenceDiagram participant MQTT客户端A participant MQTT Broker participant MQTT客户端B autonumber MQTT客户端A ->> MQTT Broker: SUBSCRIBE MQTT Broker ->> MQTT客户端A: SUBACK MQTT客户端B ->> MQTT Broker: PUBLISH MQTT Broker ->> MQTT客户端A: PUBLISH

SUBACK包含以下两个字段:数据包标识符(PacketID)和返回代码列表。

字段名说明
PacketID用于客户端识别出该响应消息与哪条SUBSCRIBE报文相关联
Return Code用于客户端判断是否订阅成功。返回码的个数与SUBSCRIBE报文中的订阅主题一一对应。取值结果如下表所示:

返回码是二进制数值,表示MQTT代理支持订阅主题的QoS级别。

返回码的取值说明
0表示代理在该主题上允许的QoS最大级别为0,亦即最多一次。
1表示代理在该主题上允许的QoS最大级别为1,亦即至少一次。
2表示代理在该主题上允许的QoS最大级别为2,亦即刚好一次。
128表示代理不接受订阅。失败的原因可能是客户端没有足够的权限订阅主题、主题格式不正确或其他原因。

UNSUBSCRIBE

在MQTT中,当客户端需要取消订阅主题时,可以向代理发送一条UNSUBSCRIBE报文。

与SUBSCRIBE报文类似,拥有两个字段数据包标识符与待取消订阅的主题列表。

字段名说明
PacketID用于确保客户端识别出与UNSUBSCRIBE相关联的相应消息。
Topic List客户端想要取消订阅的一个或多个主题的列表。

UNSUBACK

当MQTT接收到客户端发送的UNSUBSCRIBE报文后,会响应一条UNSUBACK确认报文,用于通知客户端该订阅已经被删除。

UNSUBACK报文包含了两个字段,分别是数据包标识符(PacketID)与返回码(Return Code)

报文内容如下图:

交互流程如下图:

sequenceDiagram participant MQTT客户端 participant MQTT Broker autonumber MQTT客户端 ->> MQTT Broker: UNSUBSCRIBE MQTT Broker ->> MQTT客户端: UNSUBACK
字段名说明
PacketID用于客户端识别出该响应消息与哪条UNSUBSCRIBE相关联
Return Code用于客户端判断是否取消订阅成功。0表示成功取消订阅,17表示由于无效或格式不正确的主题而取消失败。

当MQTT客户端接收到代理发送的UNSUBACK报文之后,客户端就可以已经删除UNSUBSCRIBE报文中取消订阅的主题。