MQTT5协议报文格式


1 概述

MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的"轻量级"通讯协议,该协议构建于TCP/IP协议上,由IBM在1999年发布。MQTT最大优点在于,可以以极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务。作为一种低开销、低带宽占用的即时通讯协议,使其在物联网、小型设备、移动应用等方面有较广泛的应用。

MQTT是一个基于客户端-服务器的消息发布/订阅传输协议。MQTT协议是轻量、简单、开放和易于实现的,这些特点使它适用范围非常广泛。在很多情况下,包括受限的环境中,如:机器与机器(M2M)通信和物联网(IoT)。其在,通过卫星链路通信传感器、偶尔拨号的医疗设备、智能家居、及一些小型化设备中已广泛使用。

注:由于业务用上了MQTT作为设备通讯协议内容,此篇文章为总结几篇mqtt报文解析的好文再加上mqtt官方文档出的,故此为整理备忘文。


2 控制报文格式


MQTT控制报文由三部分组成:固定头(Fixed header)+可变头(Variable header)+有效载荷(Payload) 

Fixed header固定头部,MQTT协议分很多种类型,如连接,发布,订阅,心跳等。其中固定头是必须的,所有类型的MQTT协议中,都必须包含固定头
Variable header可变头部,可变头部不是可选的意思,而是指这部分在有些协议类型中存在,在有些协议中不存在
Payload消息载体,就是消息内容。与可变头一样,在有些协议类型中有消息内容,有些协议类型中没有消息内容

2.2 固定报头(Fixed header)

Bit

7

6

5

4

3

2

1

0

byte 1

MQTT Control Packet type

MQTT控制报文类型

Flags specific to each MQTT Control Packet type

用于指定的控制报文类型标志位

byte 2…

Remaining Length 剩余长度

2.2.1 MQTT控制报文类型(MQTT Control Packet type)

        第一个字节的7-4位,一共4位,可表示16个数字,除0 禁止使用以外,剩余15个数字各表示一个控制报文类型,如图所示:

Name

名称

Value

Direction of flow

报文流动方向        

Description

描述

Reserved

0

禁止

Reserved (预留)

CONNECT

1

客户端到服务器

Client request to connect to Server

客户端连接到服务器

CONNACK

2

Server to Client

Connect acknowledgment

连接确认

PUBLISH

3

Client to Server

          or

Server to Client

Publish message

发布消息

PUBACK

4

Client to Server

          or

Server to Client

Publish acknowledgment

发布确认(QoS 1)

PUBREC

5

Client to Server

          or

Server to Client

Publish received (assured delivery part 1)

发布收到(QoS 2保证交付第一步)

PUBREL

6

Client to Server

          or

Server to Client

Publish release (assured delivery part 2)

发布释放(QoS 2保证交付第二步)

PUBCOMP

7

Client to Server

          or

Server to Client

Publish complete (assured delivery part 3)

发布完成(QoS 2保证交付第二步)

SUBSCRIBE

8

Client to Server

Client subscribe request

客户端订阅请求

SUBACK

9

Server to Client

Subscribe acknowledgment

订阅请求确认

UNSUBSCRIBE

10

Client to Server

Unsubscribe request

取消订阅请求

UNSUBACK

11

Server to Client

Unsubscribe acknowledgment

取消订阅请求确认

PINGREQ

12

Client to Server

PING request

心跳请求

PINGRESP

13

Server to Client

PING response

心跳响应

DISCONNECT

14

Client to Server

Client is disconnecting

客户端断开连接

AUTH

15

Client to Server or Server to Client

Authentication exchange

身份验证交换

 2.2.2 标志位(Flags)

        固定报头中字节1的剩余位[3-0]包含特定于每个MQTT控制数据包类型的标志,如下所示。当标志位标记为“保留”时,它将保留供将来使用,并且必须设置为所列值[MQTT-2.1.3-1]。如果接收到无效标志,则为格式错误的数据包。

MQTT Control Packet

Fixed Header flags

Bit 3

Bit 2

Bit 1

Bit 0

CONNECT

Reserved

0

0

0

0

CONNACK

Reserved

0

0

0

0

PUBLISH

Used in MQTT v5.0

DUP

QoS

RETAIN

PUBACK

Reserved

0

0

0

0

PUBREC

Reserved

0

0

0

0

PUBREL

Reserved

0

0

1

0

PUBCOMP

Reserved

0

0

0

0

SUBSCRIBE

Reserved

0

0

1

0

SUBACK

Reserved

0

0

0

0

UNSUBSCRIBE

Reserved

0

0

1

0

UNSUBACK

Reserved

0

0

0

0

PINGREQ

Reserved

0

0

0

0

PINGRESP

Reserved

0

0

0

0

DISCONNECT

Reserved

0

0

0

0

AUTH

Reserved

0

0

0

0

DUP = Duplicate delivery of a PUBLISH packet(控制报文的重复分发标志

QoS = PUBLISH Quality of Service( PUBLISH报文的服务质量等级

RETAIN = PUBLISH retained message flag(PUBLISH报文的保留标志

2.2.3 剩余长度(Remaining Length)

        Remaining Length意思是剩余长度,即Variable Header + Payload的长度。剩余长度从Byte 2开始,最长可达4字节。所以剩余长度范围是Byte[2-5]。那么怎样确定其长度到底是1还是4呢,这取决于字节的最高位Bit 7(默认都是高字节在前),如果这个值是1,那么就继续计算字节长度,如果是0,那么就不再计算字节长度。

        消息长度可以简单理解为128进制的数据,4位长度最大可以表示128*128*128*128Byte=256MB。但是这个长度的计算有些特别,就是低位在前,高位在后(因为正常的表示方法是高位在前,低位在后),字节最高位Bit7用于标记是否需要继续计算消息长度。以下是消息长度的长度范围:

字节最小值最大值
10(0x00)127(0x7F)
2128 (0x80, 0x01)16 383 (0xFF, 0x7F)
316 384 (0x80, 0x80, 0x01)2 097 151 (0xFF, 0xFF, 0x7F)
42 097 152 (0x80, 0x80, 0x80, 0x01)268 435 455 (0xFF, 0xFF, 0xFF, 0x7F)

稍微注意一下,0x80=1000 0000,不是 1000。刚开始以为是1000,所以就没明白。

举个例子。

消息假设长度是[0X60],其二进制是01100000,字节最高位Bit7(从左边起第0位)是0,所以不需要继续往后计算。那么消息长度就是0X60,十进制数是96。

如果消息长度是[0XC1, 0XC2, 0X33],那么他们的二进制分别如下,

0xC1=1100 0001

0xC2=1100 0010

0x33=0011 0011,

第一字节最高位是1,那么需要继续向后计算,去掉标记位(0xC1%128),得到100 0001=41

第二字节最高位是1,那么需要继续向后计算,去掉标记位(0xC2%128),得到100 0010=42

第三字节最高位是0,不需要向后计算,其结果就是0x33=51

因为低位在前,高位在后,那么长度计算为Length=41 + 42*128 + 51*128*128=841001 B = 821KB

需要注意的是,消息长度=可变头部长度+消息内容长度。不包括首字节和消息长度本身,如果消息长度为5,那么说明这条消息后边还有5字节,整条消息长度为7(首字节+1位长度字节+5)。

另外如果消息长度为4字节,最后一位不能超过0X7F=127,因为如果超出这个值,其最高位Bit7是1,还需要往后计算,这与消息最大长度为4字节矛盾。所以如果出现[0XFF, 0XFF, 0XFF, 0XFF]这样的消息长度,那么接收方认为这是一条非法的消息。

2.3 可变报头(Variable header)

        某些类型的MQTT控制数据包包含可变头组件。它位于固定标头和有效负载之间。可变报头的内容因数据包类型而异。可变报头的数据包标识符字段在几种数据包类型中很常见。

2.3.1 包标识符

许多 MQTT 控制数据包类型的变量头组件包括一个两字节整数数据包标识符字段。这些 MQTT 控制数据包是 PUBLISH(其中 QoS > 0)、PUBACK、PUBREC、PUBREL、PUBCOMP、SUBSCRIBE、SUBACK、UNSUBSCRIBE、UNSUBACK。

需要数据包标识符的 MQTT 控制数据包如下所示:

MQTT Control Packet

Packet Identifier field

CONNECT

NO

CONNACK

NO

PUBLISH

YES (If QoS > 0)

PUBACK

YES

PUBREC

YES

PUBREL

YES

PUBCOMP

YES

SUBSCRIBE

YES

SUBACK

YES

UNSUBSCRIBE

YES

UNSUBACK

YES

PINGREQ

NO

PINGRESP

NO

DISCONNECT

NO

AUTH

NO

如果 PUBLISH 数据包的 QoS 值设置为 0 ,则 PUBLISH 数据包不得包含数据包标识符。
每次客户端发送一个新的 SUBSCRIBE、UNSUBSCRIBE 或 PUBLISH(其中 QoS > 0)MQTT 控制数据包时,它必须为其分配一个当前未使用的非零数据包标识符 。
每次服务器发送一个新的 PUBLISH(QoS > 0)MQTT 控制数据包时,它必须为其分配一个当前未使用的非零数据包标识符 。
在发送方处理了相应的确认数据包后,数据包标识符就可以重新使用,定义如下。在 QoS 1 PUBLISH 的情况下,这是对应的 PUBACK;在 QoS 2 PUBLISH 的情况下,它是 PUBCOMP 或原因代码为 128 或更大的 PUBREC。对于 SUBSCRIBE 或 UNSUBSCRIBE,它是对应的 SUBACK 或 UNSUBACK。
与 PUBLISH、SUBSCRIBE 和 UNSUBSCRIBE 数据包一起使用的数据包标识符为会话中的客户端和服务器单独形成了一组统一的标识符。一个数据包标识符在任何时候都不能被多个命令使用。
PUBACK、PUBREC、PUBREL 或 PUBCOMP 数据包必须包含与最初发送的 PUBLISH 数据包相同的数据包标识符。SUBACK 和 UNSUBACK 必须包含分别在相应的 SUBSCRIBE 和 UNSUBSCRIBE 数据包中使用的数据包标识符。
客户端和服务器相互独立地分配数据包标识符。因此,客户端-服务器对可以使用相同的数据包标识符参与并发消息交换。

 2.4 有效载荷(Payload)

一些MQTT控制数据包包含一个有效负载作为数据包的最后一部分。在发布包中,这是应用程序消息。控制类型所需 payload 如下图:

MQTT Control Packet

Payload

CONNECT

Required

CONNACK

None

PUBLISH

Optional

PUBACK

None

PUBREC

None

PUBREL

None

PUBCOMP

None

SUBSCRIBE

Required

SUBACK

Required

UNSUBSCRIBE

Required

UNSUBACK

Required

PINGREQ

None

PINGRESP

None

DISCONNECT

None

AUTH

None

 

参考文献:

1.MQTT协议 -- 消息报文格式_weixin_34166847的博客-CSDN博客

2.MQTT Version 5.0

3.MQTT协议报文格式解析 - 知乎

3.

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值