初识MQTT协议

736 阅读4分钟
原文链接: mp.weixin.qq.com

奇技指南

最近在看MQTT协议相关的内容,先整理收集的一些信息,以及自己的一些理解,如有错误之处,敬请纠正,有不清楚的地方,也希望能够和大家一起讨论,探讨 本篇文章,简述MQTT历史,产生所要解决的问题,以及协议的基础格式。

本文转载自HULK一线技术杂谈。

前言

MQTT协议是一个简单的中心辐射型系统:传感器、应用和设备之间的通信是通过中央代理端运行的数据中心服务实现的。其精简低带宽的特性使得它能够适用于很多应用,比如家庭自动化:包括供暖、通风、空调(HVAC)、照明、智能设备和安全等方面都采用了MQTT协议。

1

浅谈历史

MQTT协议由Andy Stanford-Clark(IBM)和Arlen Nipper(Arcom,现为Cirrus Link)于1999年发明。他们需要一种协议,以最小化电池损耗和最小带宽,通过卫星与石油管道连接。 发明之初为协议规定了几个要求:

  1. 实施简单

  2. 提供服务质量的数据传输

  3. 轻巧和带宽高效

  4. 数据不可知

  5. 持续的会话意识

2

协议格式

MQTT协议控制报文的格式包含以下三个部分,以固定报头,可变报头和有效载荷,其中固定报文头是所有的控制报文都有, 可变报头和有效载荷都是部分控制报文包含。

固定报头

固定报头是两个字节组成,其具体的格式如下所示:

控制报文类型

第一个字节的二进制位7-4无符号整数表示控制报文的类型,具体类型对应的值为:

备注: 其中预留值15已经在MQTT5中使用到AUTH中了。

标志

第一个字节的二进制位3-0包含每个MQTT控制报文类型特定的标志, 控制报文中的标志为必须按照如下表格进行设置,如果设置有问题,则接收者必须断开连接。

备注:从协议规范看出,目前只有PUBLISH的标志位是使用的,其他控制报文都是预留状态,但是必须保持上述表格的形式。

剩余长度

第二个字节表示当前报文剩余部分的字节数,包括可变报头和有效载荷。剩余长度不包括用于编码剩余长度字段本身的字节数。剩余长度字段使用一个变长度编码方案,对小于128的值使用单字节编码,超过128的值,最高有效未用于指示是否有更多的字节,因此每个字节可以编码128个数值和一个延续位,剩余长度字段最大4个字节。 举例:十进制64被编码为一个字节,十六进制表示为Ox40。十进制数字321编码为两个字节,最低有效位在前,第一个字节65+128=193,第二个字节为2。 剩余长度最大为256M的报文,而且报文是不支持分包处理的,所以MQTT协议并不适合一些数据量特别大的场景,比如视频直播等数据包比较大的场景。

可变报头

可变报头介于固定报头和有效载荷中间。不同的控制报文有着不同的可变报头,其中PacketId是一个在多个控制报文中存在一个报文。 PacketId包含两个字节,现在包含该字段的控制报文有,PUBLISH(Qos>0), PUBACK, PUBREC, PUBREL,PUBCOMP,SUBSCRIBE,SUBACK, UNSUBSCRIBE, UNSUBACK。

具体包含情况如下:

注意事项

  • PUBLISH Qos0的报文是不能又packetId的。

  • 有些对应的控制报文中的packetId必须和与该控制报文绑定的其它控制报文保持一直,例如PUBLISH Qos1对应的是PUBACK,PUBLISH Qos2对应的PUBCOMP。

  • 发送者和接收者是分开维护各自的packetId,所以会出现交互双方出现相同packetId的两个不同的控制报文。

  • 关于不能有packetId的控制报文,可能是由于packetId是可以复用的,没有办法确认可以复用的场景不能使用报文,比如Qos0的PUBLISH报文,由于没有回应,所以发送者无法得知packetId何时可以释放复用,故不允许存在该字段。

有效载荷

有效载荷即为应用消息。 目前MQTT3.1.1中包含如下的控制报文CONNECT, CONNACK, PUBLISH, PUBACK,PUBREC, PUBREL, PUBCOMP,SUBSCRIBE,SUBACK,UNSUBSCRIBE,UNSUBACK,PINGREQ,PINGRESP,DISCONNECT的协议,关于这些协议的具体格式,使用场景等将在后续的文章中给出解释。

总结

MQTT是二进制的协议,控制字段是精确到Bit级别的,单纯这一点就足以为其在物联网领域占据一席之地。 MQTT是不支持分包等机制,并不适宜一些数据包特别大的应用场景。

 360官方技术公众号 

技术干货|一手资讯|精彩活动

空·