最近在看 MQTT 协议相关的内容,先整理收集的一些信息,以及自己的一些理解,如有错误之处,敬请纠正,有不清楚的地方,也希望能够和大家一起讨论,探讨 本篇文章,简述 MQTT 历史,产生所要解决的问题,以及协议的基础格式。
前言
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 的协议,关于这些协议的具体格式,使用场景等将在后续的文章中给出解释。
3 总结
MQTT 是二进制的协议,控制字段是精确到 Bit 级别的,单纯这一点就足以为其在物联网领域占据一席之地。MQTT 是不支持分包等机制,并不适宜一些数据包特别大的应用场景。
本文转载自公众号 360 云计算(ID:hulktalk)。
原文链接:
https://mp.weixin.qq.com/s/Xf3OP0i3ohRZ-sbvjvtCnQ
评论