OneNET平台MQTT协议分析
MQTT协议是一个面向物联网应用的即时通信协议,使用TCP/IP提供网络连接,能够对负载内容实现消息屏蔽传输,开销小,可以有效降低网络流量。MQTT协议适用于设备和平台需要保持长连接的使用场景,MQTT特点在于可以实现设备间的消息单播以及组播,可以不依赖于其他服务(下发命令服务,推送服务等)实现让设备以应用服务器的方式对真实设备进行管理和控制。
正因为MQTT协议拥有这些特点,现在成文了各个物联网云平台支持的最广泛的协议,百度、阿里、亚马逊、OneNet等国内外物联网云服务提供商均支持该协议,所以在做物联网开发的过程中,有必要学习和了解一下该协议。接下来我们就以OneNET的MQTT接入协议为例,学习一下该协议个通讯。
硬件连接环境:麒麟座迷你开发板用STlink连接到PC的USB口
软件开发环境:Keil MDK5.25编辑麒麟座mini开发板官方例程”6.ESP8266-MQTT_TYPE3-LED”
网络环境:PC机以太网卡连接路由器接入互联网,Windows10无线网卡建立热点,麒麟座开发板的ESP8266经过热点接入互联网。
抓包工具:Wireshart抓取以太网卡的数据包,设置过滤条件为”ip.addr == 183.230.40.39”,只显示与OneNET MQTT服务器通讯的数据包。
模拟器:,在PC上可以模拟嵌入式设备通讯。
参考文档:OneNET官方MQTT文档:”MQTT.docx”,MQTT中文文档MQTT.PDF
交互过程:连接权鉴,数据上报,命令下发,断开连接。
一、连接权鉴
首先在修改官方例程中的参数信息,把WiFi名称和密码改成使用PC无线网卡模拟的热点网络,OneNET服务器的IP地址和端口号确保为”183.230.40.39”和”6002”,onenet.c中的PROID、DEVID、AUTH_INFO修改为项目中的真实值。
编译并下载程序到麒麟座迷你开发板,在PC上使用Wireshark开始抓取以太网卡的数据包,
设置过滤条件为”ip.addr == 183.230.40.39”,只显示与OneNET MQTT服务器通讯的数据包。给麒麟座开发板上电,等待几秒钟后,就可以看到开发板与OneNET服务器通讯的数据包了。
数据包中前三帧为开发板与OneNET服务器建立TCP连接的三次握手信息,这个是开发板给ESP8266发送建立TCP连接指令后,ESP8266与服务器之间自动建立的。
数据包的第四帧至第五帧为麒麟座开发板项OneNET发送的鉴权信息和服务区应答。第六帧和第七帧是OneNET服务器返回的鉴权结果信息和ESP8266的应答。
在以上过程中,我们作为设备端开发人员,只需要了解第四帧的鉴权信息发送和第六帧的服务器鉴权结果返回就可以了。
接下来重点分析第四帧数据,次帧数据总计有114字节,去除以太网头14字节,IP头20字节,TCP头20字节,剩余的TCP有效载荷共计60字节。
根据MQTT报文协议中规定,每一个MQTT包总共包含三部分:
1、Fixed Header部分定义如下:
根据抓包的数据,TCP负载的第一个字节是0x10,对应表格可以得知,MQTT Packet Type值为1,名称为CONNECT开源mqtt服务器,其功能是客户端请求与服务器建立连接。其第二个字节的0x3a为表格中的Remaining Length字段,为数据包的长度。
根据MQTT协议规定,剩余长度(Remaining Length)表示当前报文剩余部分的字节数,包括可变报头和负载的数据。剩余长度不包括用于编码剩余长度字段本身的字节数。0x3a为十进制的58,这个数正好是TCP负载的60字节减去固定报头的两个字节长度。至于如何判断剩余长度占用的字节数,MQTT协议是这么规定的:
剩余长度字段使用一个变长度编码方案,对小于128的值它使用单字节编码。更大的值按下面的方式处理。低7位有效位用于编码数据,最高有效位用于指示是否有更多的字节。因此每个字节可以编码128个数值和一个延续位(continuaTIon bit)。剩余长度字段最大4个字节。
根据以上定义,0x3a的二进制最高位为0,可以判定数据长度为1字节。
固定报头的部分分析完成后,根据下表进行判断:
2、CONNECT类型的消息是有可变报头和负载的。对于可变报头部分,按照以下格式编码:
对照抓包数据:
其中byte1-byte6是固定值,表格与数据完全对应。Byte7表示MQTT协议版本,这个必须固定为4,即3.1.1版,OneNET只支持这一版本协议,不支持更早版本的协议。
在Byte8中,user flag与password flag平台不允许匿名登陆,因此这两个标志位在连接时必须设置为1,否则认为协议错误,平台将会断开连接。所以该字节数据为0xC0。
Byte9-10为保持连接(Keep Alive),是一个以秒为单位的时间间隔,表示为一个16位的字,它是指在客户端传输完成一个控制报文的时刻到发送下一个报文的时刻,两者之间允许空闲的最大时间间隔。如果保持连接的值非零,并且服务端在一点五倍的保持连接时间内没有收到客户端的控制报文,它必须断开客户端的网络连接,认为网络连接已断开。OneNET规定最短120秒,最长65535秒,这里设置的事0x0100,也就是256秒。
3、负载部分
负载部分的数据是按照以下格式编码
对照数据:
0x0008为域一的字符串长度,这里是8字节,内容为ASCII码的“31421353”,正好是源码中DEVID,也就是设备ID(DeviceID);0x0006为域二的字符串长度,这里是6字节,内容为ASCII码的“141215”,正好是源码中PROID,也就是产品ID(ProduceID);0x001C为域三的字符串长度,这里是28字节,内容为ASCII码的”dpsO9ruH0aTZublG9g5SvBtFSEQ=”,正好是源码中AUTH_INFO,也就是产品ID(AuthInfo);
至此,上传的鉴权信息就分析完毕了,服务器接收到鉴权信息后首先会有一个应答包,同时进行鉴权,鉴权完毕后会下发结果给客户端:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论