09月07, 2018

MQTT协议

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


浅谈历史

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

  1. 实施简单
  2. 提供服务质量的数据传输
  3. 轻巧和带宽高效
  4. 数据不可知
  5. 持续的会话意识

协议格式

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。

具体包含情况如下 控制报文PacketId

注意事项

  1. PUBLISH Qos0的报文是不能又packetId的。
  2. 有些对应的控制报文中的packetId必须和与该控制报文绑定的其它控制报文保持一直,例如PUBLISH Qos1对应的是PUBACK,PUBLISH Qos2对应的PUBCOMP。
  3. 发送者和接收者是分开维护各自的packetId,所以会出现交互双方出现相同packetId的两个不同的控制报文。
  4. 关于不能有packetId的控制报文,可能是由于packetId是可以复用的,没有办法确认可以复用的场景不能使用报文,比如Qos0的PUBLISH报文,由于没有回应,所以发送者无法得知packetId何时可以释放复用,故不允许存在该字段。

有效载荷

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

总结

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

本文链接:https://www.opsdev.cn/post/MQTT协议格式简介.html

-- EOF --

Comments

评论加载中...

注:如果长时间无法加载,请针对 disq.us | disquscdn.com | disqus.com 启用代理。