有了上一篇文章提出的消息接收与处理架构后,我们很容易就能在其基础上实现 QoS1 和 QoS2 级别消息的收发了。这篇文章首先会分析 QoS1 和 QoS2 级别的通信过程以及 PUBACK、PUBREC、PUBREL 以及 PUBCOMP 四种报文的结构。最后,还是和以前的文章一样,我们会继续完善之前的代码,实现 QoS1 和 QoS2 消息的收发代码,并进行实战。
QoS1 和 QoS2 的通信过程
QoS1:至少分发一次
服务质量确保消息至少送达一次。QoS1 的 PUBLISH 报文的可变报头中包含一个报文标识符,需要 PUBACK 报文确认。
对于 QoS 1 的分发协议发送者:
- 每次发送新的应用消息都必须分配一个未使用的报文标识符。
- 发送的 PUBLISH 报文必须包含报文标识符且 QoS = 1,DUP = 0。
- 必须将这个 PUBLISH 报文看作是未确认的 ,直到从接收者那收到对应的 PUBACK 报文。
对于 QoS 1 的分发协议接收者:
- 响应的 PUBACK 报文必须包含一个报文标识符,这个报文标识符来自接收到的 PUBLISH 报文。
- 发送了 PUBACK 报文之后,接收者必须将将任何包含相同报文标识符的入站 PUBLISH 报文当作一 个新的消息,并忽略它的 DUP 标志的值。
大致流程
QoS2 保证分发一次
这是最高等级的服务质量,消息丢失和重复都是不可接受的。QoS 2 的 PUBLISH 报文的接收者使用一个两步确认过程来确认收到。
对于 QoS 2 的分发协议发送者:
- 必须给要发送的新应用消息分配一个未使用的报文标识符。
- 发送的 PUBLISH 报文必须包含报文标识符且报文的 QoS = 2, DUP = 0。
- 必须将这个 PUBLISH 报文看作是未确认的 ,直到从接收者那收到对应的 PUBREC 报文。
- 收到 PUBREC 报文后必须发送一个 PUBREL 报文。PUBREL 报文必须包含与原始 PUBLISH 报文相同的报文标识符。
- 必须将这个 PUBREL 报文看作是未确认的 ,直到从接收者那收到对应的 PUBCOMP 报文。
- 一旦发送了对应的 PUBREL 报文就不能重发这个 PUBLISH 报文。
对于QoS 2的分发协议接收者:
- 响应的 PUBREC 报文必须包含报文标识符,这个标识符来自接收到的 PUBLISH 报文。
- 在收到对应的 PUBREL 报文之前,接收者必须发送 PUBREC 报文确认任何后续的具有相同标识符 的 PUBLISH 报文。 在这种情况下,它不能重复分发消息给任何后续的接收者。
- 响应 PUBREL 报文的 PUBCOMP 报文必须包含与 PUBREL 报文相同的标识符。
- 发送 PUBCOMP 报文之后,接收者必须将包含相同报文标识符的任何后续 PUBLISH 报文当作一 个新的发布。
大致流程
报文结构
这四种响应报文结构都非常简单,均没有有效负载部分,可变报头都仅仅包含报文标识符,我们来快速过一下:
PUBACK 报文
PUBACK 报文是对 QoS 1 等级的 PUBLISH 报文的响应。
固定报头
剩余长度表示可变报头的长度。对 PUBACK 报文这个值等于 2
可变报头
包含等待确认的 PUBLISH 报文的报文标识符。
PUBREC
PUBREC 报文是对 QoS 等级 2 的 PUBLISH 报文的响应。它是 QoS 2 等级协议交换的第二个报文。
固定报头
剩余长度表示可变报头的长度。对 PUBREC 报文这个值等于 2
可变报头
包含等待确认的 PUBLISH 报文的报文标识符。
PUBREL
PUBREL 报文是对 PUBREC 报文的响应。它是 QoS 2 等级协议交换的第三个报文。
固定报头
PUBREL 控制报文固定报头的第 3,2,1,0 位是保留位,必须被设置为 0,0,1,0。服务端必须将其它的任何值都当做是不合法的并关闭网络连接。
可变报头
可变报头包含与等待确认的 PUBREC 报文相同的报文标识符。
PUBCOMP
PUBCOMP 报文是对 PUBREL 报文的响应。它是 QoS 2 等级协议交换的第四个也是最后一个报文。
固定报头
剩余长度表示可变报头的长度。对 PUBCOMP 报文这个值等于 2。
可变报头
可变报头包含与等待确认的 PUBREL 报文相同的报文标识符。