发布与订阅流程
- ClientA 连接到 Broker;
- ClientB 连接到 Broker,并订阅主题 Topic1;
- ClientA 发送给 Broker 一条消息,主题为 Topic1;
- Broker 收到 ClientA 的消息,发现 ClientB 订阅了 Topic1,然后将消息转发到 ClientB;
- ClientB 从 Broker 接收到该消息。
消息离线接收
接收离线的消息需要 Client 使用持久化会话,且发布时消息的 QoS 不小于 1。
Publisher 和 Subscriber
Publisher 和 Subscriber 是相对于 Topic 来说的身份,如果一个 Client 向某个 Topic 发布消息,那么它就是 Publisher;如果一个 Client 订阅了某个 Topic,那么它就是 Subscriber。
Sender 和 Receiver
Sender 和 Receiver 是相对于消息传输方向的身份,例子:
- 当 ClientA 发布消息时,它发送给 Broker 一条消息,那么 ClientA 是 Sender,Broker 是 Receiver;
- 当 Broker 转发消息给 ClientB 时,Broker 是 Sender,ClientB 是 Receiver。
PUBLISH
PUBLISH 数据包是用于在 Sender 和 Receiver 之间传输消息数据的,也就是说,当 Publisher 要向某个 Topic 发布一条消息的时候,Publisher 会向 Broker 发送一个 PUBLISH 数据包;当 Broker 要将一条消息转发给订阅了某条主题的 Subscriber 时,Broker 也会向 Subscriber 发送一条 PUBLISH 数据包。
固定头
- 消息重复标识(DUP flag):1bit,0 或者 1,当 DUP flag = 1 的时候,代表该消息是一条重发消息,因 Receiver 没有确认收到之前的消息而重新发送的。这个标识只在 QoS 大于 0 的消息中使用。
- QoS:2bit,0、1 或者 2,代表 PUBLISH 消息的 QoS level。
- Retain 标识(Retain flag):1bit,0 或者 1,在从 Client 发送到 Broker 的 PUBLISH 消息中被设为 1 的时候,Broker 应该保存该条消息,当之后有任何新的 Subscriber 订阅 PUBLISH 消息中指定的主题时,都会先收到该条消息,这种消息也叫 Retained 消息;在从 Broker 发送到 Client 的 PUBLISH 消息中被设为 1 的时候,代表该条消息是一条 Retained 消息。
可变头
- 数据包标识( Packet Identifier):2bit,用来标识一个唯一数据包,数据包标识只需要保证在从 Sender 到 Receiver 的一次消息交互(比如发送、应答为一次交互)中保持唯一。只在 QoS 不小于 1 的消息中使用,因为只有 QoS 不小于 1 的消息有应答流程。
- 主题名称(Topic Name):主题名称是一个 UTF-8 编码的字符串,用来命名该消息发布到哪一个主题,Topic Name 可以是长度大于等于 1 任何一个字符串(可包含空格),但是在实际项目中,我们最好还是遵循以下一些最优方法。
- 主题名称应该包含层级,不同的层级用 / 划分,比如,2 楼 201 房间的温度感应器可以用这个主题:“home/2ndfloor/201/temperature”。
- 主题名称开头不要使用 /,例如:“/home/2ndfloor/201/temperature”。
- 不要在主题中使用空格。
- 只使用 ASCII 字符。
- 主题名称在可读的前提下尽量短。
- 主题是大小写敏感的,“Home” 和 “home” 是两个不同的主题。
- 可以将设备的唯一标识加到主题中,比如:“warehouse/shelf/shelf1_ID/status”。
- 主题尽量精确,不要使用泛用的主题,例如在 201 房间有三个传感器,温度、亮度和湿度,那么你应该使用三个主题名称:“home/2ndfloor/201/temperature”、“home/2ndfloor/201/brightness”和“home/2ndfloor/201/humidity”,而不是让三个传感器都使用“home/2ndfloor/201”。
- 以 $ 开头的主题属于 Broker 预留的系统主题,通常用于发布 Broker 的内部统计信息,比如 $SYS/broker/clients/connected,应用程序不要使用 $ 开头的主题收发数据。
消息体
PUBLISH 消息的消息体中包含的是该消息要发送的具体数据,数据可以是任何格式的,二进制数据、文本、JSON 。
订阅
- Client 向 Broker 发送一个 SUBSCRIBE 数据包,其中包含了 Client 想要订阅的主题以及其他一些参数;
- Broker 收到 SUBSCRIBE 数据包后,向 Client 发送一个 SUBACK 数据包作为应答。
SUBSCRIBE
可变头
- 数据包标识(Packet Identifier):两个字节,用来唯一标识一个数据包,数据包标识只需要保证在从 Sender 到 Receiver 的一次消息交互中保持唯一。
消息体
- 订阅列表(List of Subscriptions):SUBSCRIBE 的消息体中包含 Client 想要订阅的主题列表,列表中的每一项由订阅主题名和对应的 QoS 组成。
SUBACK
可变头
- 数据包标识(Packet Identifier):两个字节,用来唯一标识一个数据包,数据包标识只需要保证在从 Sender 到 Receiver 的一次消息交互中保持唯一。
消息体
- 返回码:
返回码 | 含义 |
0 | 订阅成功, 最大可用QoS为0 |
1 | 订阅成功,最大可用QoS为1 |
2 | 订阅成功, 最大可用QoS为2 |
128 | 订阅失败 |