上一节我们使用了网络调试助手来作为一个客户端,通过手动的方式连接Mqtt服务器以及发布消息。这一节我们继续来讲mqtt协议的消息发布。
首先呢来说说消息的服务质量,也就是Qos,即:保证消息传递的次数。
Qos有三种:
00:最多一次,即:<=1
01:至少一次,即:>=1
10:一次,即:=1
11:预留
上一次我们使用了00,也就是说最多发送一次,所以消息发出去后服务器并不会返回数据,这种方式虽然方便,但是有明显的缺陷,那就是数据未必会到达服务器端,所以只适用于对数据要求不高的情况,丢几个数据影响也不大的项目。这次我们来说说另外两种情况。
(1)QoS=00
首先来回顾一下上一节的两个指令,首先发送mqtt服务器连接指令:
10 19 00 06 4d 51 49 73 64 70 03 c2 01 2c00 05 4d 61 6b 65 72 00 01 72 00 01 72
待服务器返回20 02 00 00后发送:
30 04 00 01 73 68
第一个字节30对应的二进制位0011 0000
0011就是Publish(发布)消息。
0000就是QoS为00(中间两位),只发送一次。Dupflag(第一位)和Retain(最后一位)都设置为0,具体含义自己看前面的解释。
(2)QoS=01
现在我们要将Qos设为01,所以第一个字节就变成了0011 0010,对应的16进制就是32,然后发送的数据就要改为
32 06 00 01 73 00 03 68
比原来的多了两个字节,第一个32就不说了,第二个06是之后的字节数,也不解释了,再之后00 01指的是主题名的字节数,这里我们订阅的主题为字母”s”对应的ascii码的十六进制就是73,然后后面多了两个字节00 03,这两个字节其实你可以随意写,并没有具体限定,但是必须是两个字节,再之后的68就是我们要发送的消息的ascii码对应的十六进制了,68对应的字母为“h”,先不多说,大家连接成功mqtt服务器后,也就是收到了20 02 00 00后发送上面的指令,看看结果。
这次发送后服务器就有了返回,返回的是40 02 00 03,40是固定头,02是后面的字节数,00 03就是我们在发送数据时主题与消息中间夹着的两个字节,尝试着改一下这两个字节,例如改成99 99,也就是我们发送的数据改成
32 06 00 01 73 99 99 68
收到了40 02 99 99,看到这里你应该就明白了,返回的99 99就是我们发出去的,也就是你可以根据这两个字节是否和你发送时设定的一样来判断数据有么有成功发送。这就是Qos设为01时的情况,也就是服务器会返回你夹在主题和消息中的两个字节。
(3)QoS=10
下面来说说Qos为10时的情况,同样当Qos为10时,发送的固定头部就变成了0011 0100对应的十六进制就是34,然后我们将数据修改成:
34 06 00 01 73 99 99 68
这个和Qos为01时差不多,同样在主题和消息中间加了两个字节的数据,这个数据可以随意写,我同样用99 99吧。发送后你会收到50 02 99 99
与上一种差不多,但是此时你可以继续发送60 02 99 99,用来告诉服务器我收到返回的数据了,服务器收到后会继续返回70 02 99 99
至此数据发送完毕,也就是客户端和服务器都确定数据发送成功了。
那么Qos=01和10在数据接收上有什么不一样么?我们打开浏览器端的Websocket客户端来看看。先发送Qos=01的数据,也就是
32 06 00 01 73 99 99 68
每发送一次订阅的客户端就会收到一次
再来试试Qos=10的,也就是
34 06 00 01 73 99 99 68
无论你发送几遍,订阅了的客户端只收到一次
直到你发送60 02 99 99告诉服务器你收到了,然后服务器返回70 02 99 99后才能发送下一次数据。也就是确保数据只收到一遍。因为在物联网具体的数据发送中,经常会遇到因为各种原因数据发送不成功的情况,我们来假设物联网硬件的一次Qos为10的数据发送,首先硬件发送了一个数据,服务器收到了数据,但是服务器返回到硬件的数据却丢失了,所以硬件不知道服务器收到了数据,它可能会被设计成再发一遍,无线网络情况下什么都有可能发生的,所以服务器会再次收到数据,这样订阅这个主题的客户端同一个数据就收到两次了。这时如果选择的时Qos=10,就不一样了,硬件先发一个数据,服务器收到但是返回硬件的数据丢失,硬件再发一遍,服务器收到继续返回数据,但是订阅这个主题的客户端第二次不会收到数据的,这次硬件端收到了返回的服务器数据,然后再次发送确认数据,这个确认数据可以多次发送,直到服务器再次返回消息,这样一次数据发送才完成,发送端肯定发送一次数据,订阅端也肯定收到一次。
好吧,根据上面的例子,关于Qos取不同值时的三种数据发送相信你应该了解了,具体采用哪种要根据你想完成什么样的功能来定的。这一节课就讲这么多吧,大家可以自己试一试。
有同学可能觉得有必要搞清楚Mqtt协议的具体细节么,很多硬件都已经集成了Mqtt协议了,还有一堆的库可以调用。事实也的确如此,但是作为一个硬件开发的小白,能先搞清楚具体的细节不是更容易成为大牛么,哈哈,如果想直接在几分钟内就照着教程做出一个物联网作品,那我的这个教程可能并不适用你哦,我更多的是从最基本的地方下手,所以后面关于esp8266,Arduino程序我都很少用到别人写的库哦,全部自己写,务必能自己把控整个过程,这种作法好像有点反潮流哦,但是我觉得这样才能学的更透彻吧。