MENU

MQTT协议(七)——QoS2发布

2018 年 02 月 02 日 • MQTT协议

QoS2的发布共需要四条报文,以确保接收者收到且仅收到一次消息。

一、场景示意图

QQ截图20180202114738.png

二、协议简述

PUBLISH报文可以参加MQTT协议(五)——QoS0发布。PUBLISH REC,PUBLISH REL,PUBLISH COMP报文的结构基本一致。

  1. 固定报文头。第一个字节是控制报文标识符,紧接着的字节为报文的剩余长度,这个剩余长度是不包含固定报文头的;
  2. 报文标识符。共两个字节MSB、LSB。所以1中的报文剩余长度始终为2。

三、QoS2为何可以保证消息恰好到达一次呢?

  1. 对于QoS0,我们很容易思考,消息发送之后如果遇到网路不通等情况,消息将会丢失,那么接收者最多只能接收一次。
  2. 而对于QoS1而言,发送者PUBLISH报文之后如果该报文丢失,那么发送者过段时间没有收到ACK报文则会重新发送该报文,这样是没有影响的。

QQ截图20180202114738.png

但是当发送者PUBLISH报文发送成功,但是接收者的ACK发送失败时,超时之后发送者会再次发送PUBLISH报文。对于接收者而言,即使msg id是一样的,但是MQTT协议中是允许msg id重用的(当ACK确认之后),所以接收者会回复ACK并再次处理该消息。也就是说接收者将不止一次的接收到该则消息。

QQ截图20180202114738.png

  1. 当QoS=2时,情况将更加复杂。首先我们知道如果发送者发出的PUBLISH报文丢失时是不会造成实质性的影响的,大不了再重发一次。但是如果接收者的PUBLISH REC报文丢失时,发送者在超时后会重新再发送一份,这样接收者将再次收到相同msg id的PUBLISH报文,但是由于接收者处于等待PUBLISH REL的状态,并没有将msg id释放掉,所以再次收到的消息将被忽略掉(这里是QoS1与QoS2的根本区分所在,也就是当真正携带主题的报文到来时,QoS1会处理到重复报文,但是QoS2将忽略掉)。

QQ截图20180202114738.png

同理当发送者接收到PUBLISH REC报文后,需要发送PUBLISH REL给接收者。如果该报文半路丢失,超时之后接收者将会重新发送PUBLISH REC报文,发送者再确认msg id后将会再次发送PUBLISH REL。或者发送者自己重新发送一份PUBLISH REL报文,亦或者两件情况同时发送发生,但是多次接收与发送PUBLISH REC与PUBLISH REL并不会造成报文内容的多次接收,因为报文内容在PUBLISH报文中。

接收者再收到PUBLISH REL之后,需要回复PUBLISH CMP报文,处理流程与上面叙述一样。发送者如果没有收到PUBLISH CMP报文,它会怀疑是否是自己的PUBLISH REL报文没有发送成功,将会再次发送PUBLISH REL报文。由于在发送完PUBLISH CMP报文之后,所有关于PUBLISH报文的信息将被释放掉,接收者虽然查找不到对应msg id的消息,但是回复PUBLISH CMP报文并不会造成影响。

最后编辑于: 2018 年 03 月 25 日