IOT-MQTT协议-控制包格式

2.1 MQTT控制包的结构

MQTT协议通过以定义的方式交换一系列MQTT控制数据包来工作。本节介绍这些数据包的格式。

MQTT控制包最多由三部分组成,总是按照以下顺序组成,如图2.1所示 - MQTT控制包的结构

 

图2.1 - MQTT控制包的结构

固定标头,存在于所有MQTT控制数据包中

变量头,存在于某些MQTT控制包中

有效负载,存在于某些MQTT控制数据包中

2.2固定标题

每个MQTT控制包都包含一个固定的头。图2.2-固定标题格式说明了固定标题格式。

 

图2.2 - 固定标题格式

7

6

5

4

3

2

1

0

字节1

MQTT控制包类型

特定于每个MQTT控制数据包类型的标志

字节2 ...

剩余长度

 

2.2.1 MQTT控制包类型

位置:字节1,位7-4。

表示为4位无符号值,值列于表2.1 - 控制数据包类型

 

表2.1 - 控制数据包类型

名称

流动方向

描述

Reserved 

0

被禁止

保留的

CONNECT

1

客户端到服务器

客户端请求连接到服务器

CONNACK

2

服务器到客户端

连接确认

PUBLISH

3

客户端到服务器

          或

服务器到客户端

发布消息

PUBACK

4

客户端到服务器

          或

服务器到客户端

发布确认

PUBREC

客户端到服务器

          或

服务器到客户端

收到发布(保证交付第1部分)

PUBREL

6

客户端到服务器

          或

服务器到客户端

发布发布(保证交付第2部分)

PUBCOMP

7

客户端到服务器

          或

服务器到客户端

发布完整(保证交付第3部分)

SUBSCRIBE

8

客户端到服务器

客户订阅请求

SUBACK

9

服务器到客户端

订阅确认

UNSUBSCRIBE

10

客户端到服务器

取消订阅请求

UNSUBACK

11

服务器到客户端

取消订阅确认

PINGREQ

12

客户端到服务器

PING请求

PINGRESP

13

服务器到客户端

PING响应

DISCONNECT

14

客户端到服务器

客户端优雅断开并告诉服务器

Reserved

15

被禁止

保留的

         

 

2.2.2 Flags  标志

固定报头中字节1的其余位[3-0]包含特定于每个MQTT控制包类型的标志,如下面的表2.2-标志位所列。如果标志位在表2.2中标记为“保留” - 标志位,则保留供将来使用,并且必须设置为该表 [MQTT-2.2.2-1]中列出的值。如果收到无效标志,接收方必须关闭网络连接[MQTT-2.2.2-2] 有关处理错误的详细信息,请参见第4.8 

 

   表2.2 - 标志位

控制包

固定标头标志

第3位

第2位

第1位

位0

CONNECT

保留的

0

0

0

0

CONNACK

保留的

0

0

0

0

PUBLISH

用于MQTT 3.1.1

DUP 1

QoS 2

QoS 2

保留3

PUBACK

保留的

0

0

0

0

PUBREC

保留的

0

0

0

0

PUBREL

保留的

0

0

1

0

PUBCOMP

保留的

0

0

0

0

SUBSCRIBE

保留的

0

0

1

0

SUBACK

保留的

0

0

0

0

UNSUBSCRIBE

保留的

0

0

1

0

UNSUBACK

保留的

0

0

0

0

PINGREQ

保留的

0

0

0

0

PINGRESP

保留的

0

0

0

0

DISCONNECT

保留的

0

0

0

0

 

DUP 1        =重复发送发布控制包

QoS 2        =发布服务质量

RETAIN 3 = 发布保留标志

有关PUBLISH控制包中DUP,QoS和RETAIN标志的说明,请参见第3.3.1节。

2.2.3 Remaining Length  剩余长度

位置:从字节2开始。

 

剩余长度是当前数据包中剩余的字节数,包括变量头和有效负载中的数据。剩余长度不包括用于编码剩余长度的字节。

 

剩余长度使用可变长度编码方案进行编码,该方案使用单个字节用于最多127的值。较大的值按如下方式处理。每个字节的最低有效7位对数据进行编码,最高有效位用于指示表示中有后续字节。因此,每个字节编码128个值和“连续位”。“剩余长度”字段中的最大字节数为四。

 

非规范性评论

例如,64位十进制编码为单字节,十进制值64,十六进制0x40。数字321十进制(= 65 + 2 * 128)被编码为两个字节,最不重要的是第一个。第一个字节是65 + 128 = 193.注意,最高位设置为至少指示一个后续字节。第二个字节是2。

 

非规范性评论

这允许应用程序发送大小高达268,435,455(256 MB)的控制数据包。这个数字在线上的表示是:0xFF,0xFF,0xFF,0x7F。

表2.4显示了由增加的字节数表示的剩余长度值。

 

表2.4剩余长度字段的大小

数字

1

0(0x00)

127(0x7F)

2

128(0x80,0x01)

16 383(0xFF,0x7F)

3

16 384(0x80,0x80,0x01)

2 097 151(0xFF,0xFF,0x7F)

4

2 097 152(0x80,0x80,0x80,0x01)

268 435 455(0xFF,0xFF,0xFF,0x7F)

 

非规范性评论

将非负整数(X)编码为可变长度编码方案的算法如下:

                   

       do 283
               encodedByte = X MOD 128 284
               X = X DIV 128 285
              // if there are more data to encode, set the top bit of this byte 286
              if ( X > 0 ) 287
                  encodedByte = encodedByte OR 128 288
              endif 289
                  'output' encodedByte 290
         while ( X > 0 ) 

 

其中MOD是模运算符(C中的%),DIV 是整数除法(/在C中),OR是按位或(|在C中)。

 

非规范性评论

解码剩余长度字段的算法如下:

 multiplier = 1 299
        value = 0 300
        do 301
             encodedByte = 'next byte from stream' 302
             value += (encodedByte AND 127) * multiplier 303
             multiplier *= 128 304
             if (multiplier > 128*128*128) 305
                throw Error(Malformed Remaining Length) 306
        while ((encodedByte AND 128) != 0)

 

其中AND是按位和运算符(& in C)。

 

当此算法终止时,value包含Remaining Length值。

2.3  Variable header 变量头

某些类型的MQTT控制数据包包含可变标头组件。它位于固定标头和有效负载之间。变量头的内容根据数据包类型而有所不同。变量头的包标识符字段在几种包类型中是通用的。

2.3.1包标识符

图2.3 - 数据包标识符字节

7

6

4

3

2

1

0

字节1

包标识符MSB

字节2

包标识符LSB

 

许多控制分组类型的可变报头组件包括2字节分组标识符字段。这些控制数据包是PUBLISH(其中QoS> 0),PUBACK,PUBREC,PUBREL,PUBCOMP,SUBSCRIBE,SUBACK,UNSUBSCRIBE,UNSUBACK。

 

SUBSCRIBE,UNSUBSCRIBE和PUBLISH(在QoS> 0的情况下)控制数据包必须包含非零的16位数据包标识符 [MQTT-2.3.1-1]。每次客户端发送这些类型之一的新数据包时,它必须为其分配当前未使用的数据包标识符 [MQTT-2.3.1-2]。如果客户端重新发送特定的控制数据包,那么它必须在后续重新发送该数据包时使用相同的数据包标识符。客户端处理完相应的确认数据包后,数据包标识符可以重用。在QoS 1 PUBLISH的情况下,这是相应的PUBACK; 在QoS 2的情况下,它是PUBCOMP。对于SUBSCRIBE或UNSUBSCRIBE,它是相应的SUBACK或UNSUBACK [MQTT-2.3.1-3]。 当服务器发送QoS> 0 [MQTT-2.3.1-4] 的PUBLISH时,相同的条件适用于服务器。

 

如果其QoS值设置为0,则PUBLISH数据包 不得包含数据包标识符[MQTT-2.3.1-5]

 

PUBACK,PUBREC或PUBREL数据包必须包含与最初发送的PUBLISH数据包相同的数据包标识符 [MQTT-2.3.1-6]。类似地,SUBACK和UNSUBACK必须包含分别在相应的SUBSCRIBE和UNSUBSCRIBE数据包中使用的数据包标识符 [MQTT-2.3.1-7]

 

表2.5 - 包含数据包标识符的控制数据包中列出了需要数据包标识符的控制数据包

表2.5 - 包含数据包标识符的控制数据包

控制包

数据包标识符字段

CONNECT

没有

CONNACK

没有

PUBLISH

是(如果QoS> 0)

PUBACK

PUBREC

PUBREL

PUBCOMP

SUBSCRIBE   

SUBACK

UNSUBSCRIBE 

UNSUBACK

PINGREQ

没有

PINGRESP

没有

DISCONNECT 

没有

 

客户端和服务器彼此独立地分配数据包标识符。因此,客户端服务器对可以使用相同的数据包标识符参与并发消息交换。

非规范性评论

客户端可以发送带有数据包标识符0x1234的PUBLISH数据包,然后在收到其发送的PUBLISH的PUBACK之前,从其服务器接收带有数据包标识符0x1234的不同PUBLISH。

 

   客户端服务器

   PUBLISH Packet Identifier = 0x1234 --- à

   ß -发布数据包标识符= 0x1234

   PUBACK数据包标识符= 0x1234 --- à

   ß-- PUBACK数据包标识符= 0x1234

2.4 Payload 有效载荷

某些MQTT控制数据包包含有效负载作为数据包的最后部分,如第3章所述。在PUBLISH数据包的情况下,这是应用程序消息。表2.6 - 包含有效负载的控制数据包列出了需要有效负载的控制数据包。

表2.6 - 包含有效负载的控制数据包

控制包

有效载荷

CONNECT

需要

CONNACK

没有

PUBLISH

可选的

PUBACK

没有

PUBREC

没有

PUBREL

没有

PUBCOMP

没有

SUBSCRIBE 

需要

SUBACK

需要

UNSUBSCRIBE 

需要

UNSUBACK

没有

PINGREQ

没有

PINGRESP

没有

DISCONNECT 

没有

里面可能有些google翻译不准的地方请大家多多指正!

猜你喜欢

转载自blog.csdn.net/leeahuamsg/article/details/93203206