publish报文
publish报文的发生方向
发生的方向是:双向的,既可以从客户端发往服务器端,又可以从服务器端发往客户端。
客户端使用 PUBLISH 报文发送应用消息给服务端, 目的是分发到其它订阅匹配的客户端。
服务端使用 PUBLISH 报文发送应用消息给每一个订阅匹配的客户端。
publish报文的结构
固定报头:
1、固定报头中的重发标志dup:
如果是第一次发送此报文,则置dup=0
如果是重发报文, 则置dup=1
2、服务质量等级
Qos=0
Qos=1
Qos=2
3、保留标志
保留标志的可选值: retain=1 retain=0
可变报头:
1、主题名 topicName
2、报文标识符,只有当Qos=1或2时,pub报文中才有报文标识符
有效载荷
由应用指定的数据
Qos1级别的publish报文
服务质量Qos1会确保消息至少送达一次。Qos1的publish报文的可变报头中包含一个报文标识符,需要pubAck报文确认。
对于Qos1的分发协议,发送者:
- 每次发送新的应用消息都分配一个未使用的报文标识符
- 发送的publish报文必须包含报文标识符且Qos等于1,dup等于0。
- 必须将这个publish报文看作是未确认的,直到从接收者那里收到对应的pubAck报文
对于Qos1的分发协议的接收者:
-
响应的pubAck报文必须包含一个报文标识符,这个标识符来自接收到的,已经接收所有权的
publish报文 -
发送pubAck报文之后,接收者必须将任何包含相同报文标识符的入站publish报文当作一个新的
消息,并忽略它的DUP标志的值
Qos1的协议的交互流程图
下面这张图是:Qos1的交互流程图:
mqttQos1报文交互 (3).jpg
Qos1级别的pub报文的缺陷
消息重复的问题
在上图中,我们可以看到,对于发送方来说,当它发送一个pub报文时,它会一直等待着来自对方(接收方)的消息确认报文pubAck。只有收到pubAck报文之后,它才认为该pub报文已经发送成功,否则,就会执行重试。
即: 再次发送该pub报文给客户端直到收到pubAck确认已经发生成功为止。
但是,这里有个问题,那就是: 如果接收方已经收到了pub报文,而且它也把pubAck报文发送出去了,但是由于网络状况太差或者其他原因,导致了这个pubAck报文丢失了,发送方接收不到来自接收方的pubAck确认报文。
于是,发送方就会对此pub报文进行二次重发,这样的话,接收方就又收到了一条和原来一模一样的pub报文,实际上由于接收方之前就已经收到并处理过该报文了,所以这次报文对接收方来说,就是一条重复报文。
可见,导致重复消息的原因就是: pubAck报文在网络传输中丢失造成的。
Qos2解决Qos1的重复消息问题
Qos2是最高的服务质量等级,消息丢失和重复都是不可接收的。但是使用这个服务质量等级会有额外的开销。
两步确认过程
Qos2的pub报文的接收者使用一个两步确认过程来确认收到。
发送方和接收方的处理
对于Qos2的发送方来说:
. 必须要给要发送的新应用消息分配一个未使用的报文标识符。
. 发送的pub报文必须包含报文标识符且报文的Qos等于2,dup等于0.
. 必须将这个pub报文看作是未确认的,直到从接收者那收到pubRec报文。
. 收到pubRec报文后必须发送一个pubRel报文,pubRel报文必须包含与原始的pub报文相同的报文标识符
. 必须将这个pubRel报文看作是未确认的,直到从接收者那收到对应的pubComp报文
. 一旦发送了对应的pubRel报文就不能重发这个publish报文了。
对于Qos2的接收者来说:
. 响应的pubRec报文必须包含报文标识符,这个标识符来自接收到的、已经接收所有权的publish报文。
. 在收到对应的pubRel报文之前,接收者必须发送pubRec报文确认任何后续的具有相同标识符的pub报文。
. 响应的pubRel报文的pubComp报文必须包含与pubRel报文相同的报文标识符
. 发送pubComp报文之后,接收者必须将包含相同报文标识符的任何后续的pub报文当做一个新的发布。
Qos2的交互流程
mqttQos2报文交互 .jpg我们知道,Qos1的消息重复问题的根源在于:pubAck报文的丢失导致。
所以,如果我们要解决消息的重复问题,就必须致力于解决 pubAck报文的丢失问题,在Qos2中,对应的就是pubRec报文的丢失问题。
即:确保发送方一定可以收到来自接收方的pubRec报文。所以这里就引出了:2步确认过程。
step1: 第一次使用应答机制来对pub报文进行确认,从而确保接收方一定可以接收到pub报文。
step2: 第二次使用应答机制来对pubRec报文进行确认,从而确保发送方一定可以接收到pubRec报文。
可见:
1、pubRec 是对pub的保证,确保pub不会丢失
2、pubRel 是pubRec的保证,确保pubRec不会丢失
3、pubComp是pubRel的保证,确保pubRel不会丢失
如果sender没有收到pubRec,就要重发该pub。
如果receiver没有收到pubRel,就会重发pubRec。
如果sender没有接收到pubComp,就会重发pubRel。
-
对于接收方来说,收到pubRel报文之后,它的使命就完成了。(即: 它不仅收到了pub消息,而且确信自己也已把pubRec报文送到了发送方。)
-
对于发送方来说,收到了pubRec报文,就意味着,pub报文已经被接收方确定接收了。收到了pubComp报文,就意味着,pubRel报文已经确定被接收方接收了。
网友评论