MQTT设计了一套消息传输机制,包括消息应答、存储和重传。在此套机制下,提供了三种不同层次QoS(Quality of Service):

QoS0,发送就不管了,最多一次;

QoS1,发送之后还要对方确认,所以至少一次;

QoS2,发送之后依赖MQTT消息机制,确保只有一次。

为了描述方便,把消息的发送端简称为发送方,把消息的接收端称为接收方。

Qos0表示最多发送一次,就是发送方发了一条消息后就不再发了,不管接收方有没有收到在这条消息。

Qos1表示至少发送一次,就是发送方发了一条消息后等待接收方回确认,如果没有收到还会再发。由于各种原因,接收方可能会收到多条同样的消息。

Qos2 表示接收方有且只有一次收到发送方的消息,那么问题来了,怎么保证?

结合协议,详细阐述一下。

        由于网络或者通讯双方本身的故障,接收方或者发送方都可能收不到对方的信息,所以为了防止重复发送或者消息的发送方需要对方确保某条信息收到,需要对消息进行区分,我们用消息ID来标识。

       为了描述方便,把最初发送消息的一方称为S,接收该消息的为R,消息ID为id1的消息为id1消息。

1、第一阶段

       现在S向R发送一条id1消息。等待对方应答,如果超时没有,S会重发该条消息。

2、第二阶段

       如果R第一次收到id1消息,会保存到数据库中,而同时S没有收到R的回应,当然还会继续发该条消息,这时R因为数据库有这条消息(通过ID知道),会过滤它们,当然也会排除那些S早发了的现在才来得及处理的消息。R因为收到该条消息,会向S发送应答消息ack1,带上收到的消息的ID,表示id1消息收到了。

如果R发的ack1消息,S没有收到,这时S会重发id1消息,而R也必须回应,重发ack1消息。R为什么需要S对ack1消息进行确认,因为这个消息很重要,需要让对方知道“我收到这条消息”,如果对方没有回应,R认为ack1消息丢失,需要重新发,而且也是提醒S不要再发id1消息,因为我已经收到了。

3、第三阶段

       如果S收到ack1消息,知道对方已经收到了id1的消息,也需要发应答消息ack2给R,带上消息的ID,表示“我知道你已经收到我发的id1信息了”, S为什么要发应答给R,因为R没有收到S对ack1的应答,R会一直发ack1消息。

4、第四阶段

       如果R收到ack2消息,知道“对方已经知道我收到了id1消息”,也就不再发ack1消息,而S也知道R已经收到这条消息,而R因为消息ID,确保了数据库中这条消息是唯一的,不会有重复的,这对一些重要信息很重要。如此QoS2消息的发送才算真正完成。这时为什么不需要R对ack2进行应答呢? 没有必要,因为R已经知道“对方晓得自己收到id1消息了”。还有个问题,S为什么不会关注R有没有收到ack2的消息呢,也没有必要,因为如果R没有收到ack2消息,它会一直发ack1消息。如果S发送了ack2消息后,再也没有收到ack1,说明对方已经收到ack2,否则通讯就没完没了。

更多推荐