MQTT——发布报文
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
MQTT——发布报文
发布报文的知识点并不难,只是多。
看过前面几章的读者们应该或多或少都认识服务质量QOS。
发布报文跟他的联系最紧的。
我们也清楚订阅报文里面虽然也有用到QOS,但是他却没有更进一步的联系。
往下看就知道是什么一会事了。
服务质量QOS
不管是订阅报文还是发布报文都会遇到一个问题——报文流失的问题。
所以才会有了服务质量这一说法(个人看法)。
什么意思呢?就是用来处理流失的问题。
即然报文在发送的过程中可能存在流失的问题。
那么最直接的决解方案就是重新发送,不就行了吗。
所以服务质量事实就是在表示报文要分送几次。
QOS有三个值。
分别表示着三种不同的处理报文方式。
相应的值如下
QOS 0:最多分发一次。
即是可以零次或是一次。
不过笔者认零次的情况大多数是不可能存在的。
一次到很常见。
QOS 1:至少分发一次。
QOS 2:只分发一次。
笔者在看MQTT协议文档的时候,对于QOS的分发一直有一个小问题。
笔者以为是指客户端到客户端的分发。
不过看了几遍觉得他是指客户端到服务端的分发。
那么为什么笔者会认为是客户端到客户端的分发呢?主要是笔者认为QOS是指报文到客户端的次数。
比如QOS 1说明分送到每一个符合客户端的报文至少一次。
所以才会有至少分送一次的说法。
原来一开始笔者理解错了。
所以请记住这里服务质量QOS是指客户端与服务端的分发。
所谓的分发- 次,至少一次,更不是指报文到客户端的次数。
如果分发是客户端到服务端的话。
假设服务端收到了QOS 1的报文。
那么服务端就会回发一个响应表示收到,QOS 1的处理就这样子结束了。
而服务端还要把这个报文发送到别的符合的客户端。
这个时候还是存在的报文流失的问题。
你们也清楚网络有时候就是这样子。
当然这个可能笔者多虑了。
但是服务质量QOS就是把相关的报文不停
的重发。
那么对于重数的次数MQTT肯定不可能不做一些记录。
所以固定报头的DUP作用就出来了。
重发一次就把DUP加1。
下面笔者会细说。
服务质量QOS 0 笔者喜欢用一词来形客。
管杀不管埋。
发出去之后。
收不收的到不管了。
当然笔者说的有一点过头了。
这里是指客户端向服务端发送发布报文,只要服务端接收到了。
那么客户端就在也不管了。
服务质量QOS 1的要求是至少分发一次。
如果失败的话就一直重复分发。
笔者先把流程写出来。
然后加一张图来加深理解。
1)客户端向服务端发起一个发布报文。
如果服务端没有接到。
请你继续起发不用客气。
2)服务端收到一个来看客户端的发布报文。
查看一下原来是服务质量QOS为1的报文。
服务端就必须回发一个叫发布确认(PUBACK)的报文。
而这个时候客户端也在等待着服务端的回应(好了故事就从这里开始了)。
3)客户端等了一段时间就是没有接到来自服务端的回应,没有办法客户端只能认为失败了。
在重发一次吧。
这个时候客户端就必须把固定报头里面的DUP加1了。
但是服务端事实上没有问题,并且开始给符合主题的客户端们发分信息了。
只是可能这一段时间正在处理一些事情,回应慢了。
4)客户端终于接收到了回应(PUBACK)。
结束了。
注意:图片中的红线就是一个重发的环。
从上面的流程我们就可以看出来一个问题,服务端有可能收到多次的发布报文。
那么当服务端在次接收到DUP大于0的报文,不管他,
当前普通的报文一样了处理。
同样子也要给客户端一个回应,不然他又要重发了。
那么这就意味着服务端要处理相同的发布报文问题。
可惜文档里面要求当作正常的报文来处理就行了。
即是不管是不是重发的报文,只要接到报文并且他的QOS大于0,那么给对应的客户端一个回应。
同时给符合主题的客户端们分发报文。
显然客户端们会接收到多个相同的信息了。
服务质量QOS 2表示只分发一次。
笔者在看文档MQTT 3.1里面的QOS2 处理时候,有一点不理解。
后来在去看一下MQTT 3.1.1果然写的清楚一点了。
不然笔者以为跟服务质量QOS 1没有什么区别。
让我们看一下他是什么处理才只分一次呢?
1)客户端向服务端发起一个发布报文。
如果服务端没有接到。
请你继续起发不用客气。
2)服务端收到一个来看客户端的发布报文。
查看一下原来是服务质量QOS为2的报文。
服务端处理相关操作之后,就回应一个叫PUBREC 的报文。
如果是服务质量QOS 1的话,这个时候会给符合的客户端们发送信息。
那么服务质量QOS 2这边要不要这个时候给符合主题的客户端们发送信息呢?当然这一点档文也没有特别指出来。
所以笔者认为应该是可以的。
同时服务端还要等待来自客户端的一个叫PUBREL的报文呢?
3)客户端在一段时间之后,如果没有收到相关回应的话,重发一次,同时DUP加1。
直到接收到回应(PUBREC)。
4)当前客户端接收到了来自服务端的回应(PUBREC)。
客户端就必须在回头跟服务端说一声:“我收到你的回应了”。
因为服务端一直在等客户端的回应,即是PUBREL报文。
如果客户端一直不给服务端回发一个回应,表示客户端已经收到回应。
服务端会一直重发PUBREC。
这个时候DUP有没有加1。
文档里面没有说明。
所以应该是不需要。
直到服务端接收到客户端的回应(PUBREL)。
在笔者心里面这里才是给符合主题的客户端们发送信息的时候。
5)客户端在给服务端发送PUBREL报文,说明我收到了你的回应了。
同时客户端又在等待服务端的另一个回应。
告诉客户端动作结束
了。
即是PUBCOMP报文。
6)客户端收到来自服务端的PUBCOMP报文响应。
结束了。
注意:图片中的红线就是一个重发的环。
理论上来讲服务质量QOS 2的安全等级绝对高于服务质量QOS 1。
关是步棸QOS 2就比QOS1多了二步。
而且这二步都是一个重发的环。
图片中我们可以看到。
可是如果细想一下,笔者心里面有一点不理解。
所谓的至少分一次,只分发一次好像并没有体现出来。
如QOS 2里面客户端没有接到PUBREC的报文时候,不是还是要重发一下发布报文。
那么所以只分发一次。
理解上就有一点怪怪的。
笔者也想过可能QOS 2会根据消息ID特别处理报文,让同一个报文只处理一次。
不然的话,不是还是会出现QOS 1那样子客户端们可能会收到重复的信息。
可是笔者在MQTT 文档里面没有找到。
这一点读者们自行去查看吧。
不管是QOS 1还是QOS 2。
最后都要给符合主题的客户端发送信息。
那么关键点是在什么时候发送。
虽然文档里面有指出可以在PUBACK或是PUBREC之后就可以给符合主题的客户端发送信息。
总之笔者没有找到特别指出的地方。
所以大部分都是网络说的。
QOS 1在PUBACK发出之后就可以发送给客户端信息。
QOS 2在服务端接受PUBREL之后发送给客户端信息。
当然读者们也可以自行选择吧。
发布报文结构
发布报文的格式比较单简。
即然是发布报文那么主题和发布的内容是一定少了的。
所以相对于别他报文来讲,发布报文对固定报头,可变报头,还有有效载荷都有需要。
固定报头笔者就不用多讲了。
把官方的列表拿过来大家自己看。
就是那几个常用的信息。
如下
看列表就是他的固定报头的二进制是00110000或是00110010或是00110100。
分别对应QOS 0,QOS 1,QOS2。
可变报头里面存放了俩个信息对服务端来讲很重要。
一个是主题,一个是消息ID。
除了这俩个没有别的了。
如下
官方的列表第一次看时候是有一点看不懂。
特别是byte1,byte2是什么。
如果看不懂他也没有事。
你只要明白这些是组成元素就可以了。
如上面列表的主题是“a/b”。
有三个元素组成的。
后面就是每一个元素对应的二进制。
而LSB和MSB前面讲过了。
有效载荷就是存放就是发布的内容了。
略过。
这一部分的代码笔者就不写了。
因为笔者比较赖。
只要上章读者们有去实现把相关订阅的主题保留住的话,那么发布报文的时候,只要从保留的主题中找到符合的。
然后过通主题的信息找到对应的客户端连接。
在发送信息就行了。
但是一定要记得服务质量的要求。
笔者这里只分析包的结构。
如下
服务质量QOS 0的发布报文包
图片上笔者已经标出来相关的内容。
分别为不同的颜色。
我们知道服务质量QOS 0是没有回应的。
所以只是单向的发送。
比较简单。
但是有一点要记得他好像没有消息ID。
服务质量QOS 1的发布报文包
我们可以看到跟QOS 0没有什么区别。
主要是有了消息ID。
但很重要。
服务质量QOS 1的发布报文确定(PUBACK)包
我们发现他没有有效载荷。
除了固定报头之外,就是可变报头,同时只有一个消息ID。
而且跟上面的发布报文的消息ID是相同的。
服务质量QOS 2的发布报文包
服务质量QOS 2的发布确定包(PUBREC)
相同的消息ID,没有有效载荷
服务质量QOS 2的发布确定包(PUBREL)
相同的消息ID,没有有效载荷
服务质量QOS 2的发布确定包(PUBCOMP)
相同的消息ID,没有有效载荷。