MQTT 发布,订阅 和 取消订阅-MQTT核心系列:第四章

作者:HiveMQ 团队

翻译:索隆有几把刀

欢迎来到MQTT核心系列的第四章。这个系列一共有十章,用来介绍MQTT的核心特性和概念。在这一章中,我们将着眼于MQTT中的发布,订阅和取消订阅。再前面的文章中,我们讲解过订阅发布模式的基本知识。在这一章,我们将深入到MQTT协议中的发布订阅系统的细节中去。如果你还没有读过发布订阅模式的基本知识,我们强烈建议你先去读一下前面的文章。

上周,我们了解了MQTT客户端与代理之间的连接的建立。这周我们将在此基础上讨论消息的发送和接受。

推送

MQTT客户端一旦连接到代理,就可以发送消息。MQTT利用基于主题的代理过滤消息。每一个消息都必须拥有一个主题,代理会使用该主题将消息转发给感兴趣的客户端。通常,每一个消息都拥有一个负载,它包含字节流形式的数据。MQTT是数据不可知的,客户端决定了负载的数据结构。数据发送方决定它是否要发送二进制数据,文本数据,或者甚至是XML,JSON。

在MQTT中,发送的消息里有几个属性是我们想仔细讨论的:

java mqtt订阅同一个主题两次_标识符

主题名称

主题名称是一个简单的具有层级结构的字符串。例如,“myhome/livingroom/temprature” or “Germany/Munich/Ocoberfest/people”。对于主题的细节,请看第五章。

服务质量(QoS)

QoS这个数字表示了消息的服务等级质量,它共有三个等级,分别是0,1,2。QoS决定了消息到达目标(客户端或者代理)的保障等级。更多的细节请看第6章。

保留标志(Retain Flag)

这个标志决定一个消息是否会被代理作为某主题的最后值存储。当一个新的客户端订阅这个主题的时候,它就会收到这个被保存的消息。更多的细节请看第8章。

负载(Payload)

负载里是内容的实际要传输的信息。MQTT是数据不可知的,负载里面可能是图片,任意编码的文本,加密过的数据,或者任意二进制的数据。

数据包标识符(Packat Identifier)

数据包标识符唯一标记一个指定客户端与代理之间的消息,这个标记只与QoS大于0的消息有关系。客户库或者代理负责设置内部的MQTT标志。

重复标识符(DUP flag)

这个标识符标识这个消息是否是因为之前的消息没有得到应答而重复发送的。这个标识符只与QoS大于0的消息有关。通常重复发送机制由客户端或者代理自己作为细节去实现。更多的细节请看第6章。

当客户端推送了消息给代理后,代理会读取消息,确认消息(根据QoS的等级),处理消息。处理消息的过程包括确认那些客户端订阅了该消息的主题和将消息发送给这些客户端。

java mqtt订阅同一个主题两次_客户端_02


消息发送方在消息发送过程中只需要关心消息能投送到代理哪里。一旦消息到达了代理,那么代理会负责把消息推送给消息订阅者。消息推送方不会获得反馈,无论是否有客户端对这个消息感兴趣,或者有多少人收到了这个消息。

## 订阅

如果没有人接受消息,那么发送消息是没有意义的。也就是说,没有客户端订阅这个消息的主题。为了接受感兴趣的主题的消息,客户端需要发送一个SUBSCRIBE消息给代理。这个订阅消息结构很简单,它包含一个独一无二的数据包标志符和一系列订阅信息。

java mqtt订阅同一个主题两次_java mqtt订阅同一个主题两次_03

### 数据包标识符

数据包标识符能唯一标记一条指定代理和客户端之间的消息。客户端库或者代理负责设置内部的MQTT标识符。

### 订阅集合

一条SUBSCRIBE消息能包含多个订阅。每一个订阅有一个主题和一个服务质量组成。订阅消息里的主题可以包含通配符,这样就可以订阅一个类型的主题,而不仅仅是某个特定的主题。如果对一个客户端有重复的订阅,那么代理会以最高的服务质量等级来传递这个主题的消息。

## 订阅回复(SUBACK)

为了确认订阅,代理会发送一个SUBACK确认消息给客户端。这个消息包含原先订阅消息的数据包标识符和对应订阅消息的一组返回状态码。

java mqtt订阅同一个主题两次_java mqtt订阅同一个主题两次_04

### 数据包标识符

这个数据包标识符用来标志消息的唯一标记,它和对应的订阅信息的数据包标识符一样。

### 返回码

代理会为订阅消息中的每一对主题/订阅质量返回一个返回码。例如,一个SUBSCRIBE消息里面有五个订阅,那么消息里就会有五个返回码。返回码确认订阅情况和服务质量等级。假如代理拒绝了订阅,那么SUBACK消息会包含一个失败的返回码。例如,客户端没有订阅的权限或者主题格式不对。

|  Return Code  | Return Code Response  |
 |  ----  | ----  |
 | 0  | Success - Maximum QoS 0 |
 | 1  | Success- Maximum QoS 1 |
 | 2  | Success - Maximum QoS 2 |
 | 128  | Failure |

java mqtt订阅同一个主题两次_客户端_05

在客户端成功发送一个SUBSCRIBE消息并接收到订阅成功的SUBACK消息后,它就可以收到符合订阅里的主题的每一条消息。

## 取消订阅

与SUBSCRIBE消息的对应消息就是UNSUBSCRIBE消息。这个消息能删除存在在代理中的客户端的订阅信息。UNSUBCRIBE消息的结构与SUBSCRIBE消息的结构很相似。它有一个数据包标识符和一组主题。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ObSI4FRs-1614179503787)(https://www.hivemq.com/img/blog/unsubscribe_packet.png)]

### 数据包标识符

消息标识符能唯一标记指定客户端和代理之间的消息。客户端库或者代理扶着设置内部标识符。

### 主题集合

主题集合包含客户端想取消的主题。与订阅消息不同的是,它只需要包含主题而不需要服务质量。代理会取消主题,而不用关心服务质量。

## 取消订阅回复

为了确认订阅取消情况,代理会发送一个UNSUBACK
的确认信息给客户端。这个消息只有一个原先UNSUBSCRIBE消息的数据包标识符。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I3c6o1e2-1614179503789)(https://www.hivemq.com/img/blog/unsuback_packet.png)]

### 数据包标识符

数据包标识符能唯一指定消息。如前面所说,这个值与取消订阅消息的数据包标识符一致。

在从代理收到UNSUBACK消息后,客户端就能确认取消订阅成功了。


这样我们的第四章就结束了。我们希望你能喜欢。在下一章中,我们会更加深入的学习主题如何使用。我们会学习主题的基础,怎么用通配符,并且提供一些训练例子。