开发者学堂课程【嵌入式之 RFID 开发与应用2020版:MQTT 协议格式】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/665/detail/11173
MQTT 协议格式
内容简介
一、MQTT 协议
二、MQTT 报文格式
本节内容简单学习 MQTT 协议,如果不需要进行 MQTT 协议栈开发,就不需要深度学习协议,了解协议对应用开发有一定帮助。
一、MQTT 协议
mqtt 是应用层协议,按照 TCP/IP 四层参考模型,最底层是数据链路层,然后分别是网络层,传输层,应用层,应用层是最常见的,比如 http,ftp 等,还有后面物联网会使用低功耗通信协议 CoAP, CoAP 是建立在 UDP 之上,今天学习的 MQTT是建立在 TCP 上的,所以因为 TCP 本身开销大,MQTT 功耗也高。
二、MQTT 报文格式
通信过程中,除了底层 TCP 保障传输,网络包括数据链路的一系列投靠,在应用层有自己的数据包格式。格式从大的层面可以分为 2 个,细分则有 4 个。第一个是固定控制报头,因为它永远是一个字节,一个字节分为两段,高四位和低四位,第二个是剩余数据长度,基本固定,长度不超过 4bytes,告诉我们接下来还有多少数据;第三个是可变长度报头,主要服务于 payload;第四个是有效数据载荷,根据可变报头类型变化发送变化。
1.MQTT 报文格式
Control Header |
Pakcet Length |
Variable Header |
Payload
|
1 Byte |
1- 4 Bytes |
0- x Byte |
0-y Byte |
所以整个数据长度是可变的,大概分为固定控制报头,剩余数据长度,可变长度报头,有效数据载荷。
固定控制报头固定的一个字节被分为 2 个字段,高 4 位和低 4 位。高 4bit 表示14种控制报文类型。
建议打开 MQTT 协议,所讲协议是 MQTT 建立在 3.1.1 基础上,网上可以下载翻译版和原版。
最开始就会进行协议介绍,前面会有专业术语和简单介绍。和我们所讲不同,这里是由三部分组成,由固定报头,可变报头和有效载荷组成,省略了剩余长度。
固定报头:
固定报头分为高 4 位和低 4 位,高 4 位代表 MQTT 控制报文的类型,低 4 位代表用于指定控制报文类型的标志位。
2.控制报文的类型:
去除首尾保留部分,类型有 14 个。这里标记出报文的流动方向,是客户端留向服务端还是服务端流向客户端还是都可以。比如 CONNECT 是客户端发往服务端的连接请求,就是现在有连接需求,服务器应该做出响应,而 CONNACK 是服务器表达响应,叫做连接报文确定。Publish 是发布请求,发布请求服务器和客户端都可以进行,服务器并不只是服务器,本身可以发布订阅。PUBACK 是发布确认。正常情况根据信息的服务质量,QoS0, 发布信息后就不需要再管是否收到,QoS1 级别会进行发布信息确认,服务器会回应收到,QoS2 级别通讯除了以上两次握手,还需要服务器记录消息发布方认为我释放了信息,经过了更多步骤,经历 5 个来回才完成发布,发布是最可靠的。接下来是订阅请求,SUBSCRIBE 是客户端订阅请求,SUBACK 是取消订阅,以及 UNSUBACK 是取消订阅确认。心跳包,属于可变报头约定的数据格式,可以设置心跳的时间间隔,在不低于这个间隔内必须发送一次心跳请求。还可以发起断开连接 DISCONNECT。
以上是整个 MQTT 的报文数据类型,共 14 个,有固定报头高 4 位确定。
3.标志
标志是 4 位,大致是根据控制报文类型会有对应参数,比如建立连接 CONNECT 和连接应答 CONNACK 是 0,发布记录释放完成只有一个值不一样等,根据报文类型不同,标志也不同。
DUP1 = 控制报文的重复分发标志
QoS2= PUBLISH 报文的服务质量等级
RETAIN3 = PUBLISH 报文的保留标志
PUBLISH 控制报文中的 DUP, QoS 和 RETAIN 标志的描述见 3.3.1 节。
4.剩余数据长度,剩余包括指定长度和可变报头和载荷。
剩余长度位置:从第 2 个字节开始。
剩余长度( Remaining Length ) 表示当前报文剩余部分的字节数,包括可变报头和负載的数据。剩余长度不包括用于编码剩余长度字段本身的字节数。
剩余长度字段使用一个变长度编码方案,对小于 128 的值它使用单字节编码。更大的值按下面的方式处理。低7位有效位用于编码数据,最高有效位用于指示是否有更多的字节。因此每个字节可以编码 128 个数值和一个延续位( continuation bit )。剩余长度字段最大 4 个字节。
因为剩余长度不仅表达了可变报头长度还有载荷,载荷里面除了主题还包含了内容,内容很多,所以内容理论上 4 字节情况最多能发 256MB。
(1)可变报头
根据报文类型的不同,会有不同的报文标识
协议名称 (Protocol Name )
协议级别( Protocol Level )
连接标志( Connect Flags )
保活时间( Keep Alive )
连接标识( Packet Identifier )
可变报头从协议名称开始就不包含固定头,前两个字节约定了大小端
名称( MQTT 占了 4 个字节)。协议级别在第七个字节,接下来是连接标志,属于第八个字节,这和载荷有很大关系,指出了有效载荷中的字段是否存在,比如标志是数用户名还是密码。后面是保活时间,即保存连接的时间,用了 16 位的字它占了两个字节,第九个字节和第十个字节,保持连接是以秒为单位的时间间隔,不能有小数。
保持连接( Keep Alive )是一个以秒为单位的时间间隔,表示为一个 16 位的字,它是指在客户端传输完成一个控制报文的时刻到发送下一个报文的时刻,两者之间允许空闲的最大时间间隔。客户端负责保证控制报文发送的时间间隔不超过保持连接的值。如果没有任何其它的控制报文可以发送,客户端必须发送一个 PINGREQ 报文 [MQTT-3.1.2-23]。
不管保持连接的值是多少,客户端任何时候都可以发送 PINGREQ 报文,并且使用 PINGRESP 报文判断网络和服务端的活动状态。所以在不低于给定保活时间内需要有心跳包。
所以从协议名称,协议级别,连接标志,保活时间就构成协议的头,具体内容是什么是由可变头和连接标识决定。
了解整个协议大概就是如此,具体每一个字段作用建议参考手册 3.1.1。