【EMQX 5.0】1.3 MQTT协议数据包结构

1. MQTT数据包           

        官方文档: http://mqtt.org/documentation
         MQTT数据包 由以下 三部分构成
  • 固定头(Fixed header)存在于所有MQTT数据包中,表示数据包类型及数据包的分组类标识, 如连接,发布,订阅,心跳等。
  • 可变头(Variable header)存在于部分MQTT数据包中,数据包类型决定了可变头是否存在及其 具体内容。
  • 消息体(Payload)存在于部分MQTT数据包中,表示客户端收到的具体内容。 

3.1 固定头(Fixed header

         固定头包含两部分
  • 首字节 = 数据包类型 + 标识 [类型控制字段]1字节 )
  • 剩余长度 = 当前包中剩余内容长度的字节数1 - 4字节)
         剩余长度 是当前包中剩余内容长度的字节数,包括变量头和有效负载中的数据)。剩余
长度不包含用来编码剩余长度的字节。
        剩余长度使用了一种可变长度的结构来编码,这种结构使用单一字节表示0-127 的值。大于 127 的值如下处 理。 每个字节的低7位用来编码数据,最高位用来表示是否还有后续字节 。因此每个字节可以编码 128 个值,再加 上一个标识位。剩余长度最多可以用四个字节来表示。

MQTT 最大传输数据:

        计算数据包最大 传输256MB数据
  • 一个字节2的7次方Byte,最高位用来表示是否还有后续字节
  • 4个字节 = 2的28次方Byte = 2的18次方KByte = 2的8次方MByte = 256MB

3.1.1 数据包类型 

位置:第一个字节(Byte 1) 中的 7-4个bit位 (Bit[7-4]) ,表示 4 位无符号值
  • 第一个字节的高4位确定消息报文的类型
  • 4bit位能确定16种类型
  • 00001111保留字段
        MQTT消息报文类型如下:
报文类型字段值数据方向描述7-4 bit值
保留0

禁用

保留0000
CONNECT1

Client --> Server

客户端连接到服务器0001
CONNACK2

Serer  --> Client

连接确认0010
PUBLISH3

Client<--> Server

发布消息0011
PUBACK4

Client<--> Server

发布确认(QoS1)0100
PUBREC5

Client<--> Server

消息已接收(Qos2第一阶段)0101
PUBREL6

Client<--> Server

消息释放(QoS2第二阶段)0110
PUBCOMP7

Client<--> Server

发布结束(QoS2第三阶段)0111
SUBSCRIBE8Client --> Server客户端订阅请求1000
SUBACK9Serer  --> Client服务端订阅确认1001
UNSUBACRIBE10Client --> Server客户端取消订阅1010
UNSUBACK11Serer  --> Client服务端取消订阅确认1011
PINGREQ12Client --> Server客户端发送心跳1100
PINGRESP13Serer  --> Client服务端回复心跳1101
DISCONNECT14Client --> Server客户端断开连接请求1110
AUTH(V5.0使用)15

Client<--> Server

认证数据交换1111
 

3.1.2 标志位 

位置:第一个字节中的0-3 bit (Bit[3-0]) 。意思是字节位 Bit[3-0] 用作报文的标识。
  • 首字节的低4位(bit3~bit0)用来表示某些报文类型的控制字段,实际上只有少数报文类型有控制位,如下图

(1):其中 Bit[3] 为 DUP字段 ,如果该值为 1 ,表明这个数据包是一条 重复的消息 ;否则该数据包就是第一次发布的消息。
(2): Bit[2-1]   为  Qos字段
  • QoS 0:Bit 1= 0 Bit 2=0 ,至多一次;(消息发送)
  • QoS 1:Bit 1= 1 Bit 2=0 ,至少一次;(消息发送)
  • QoS 2:Bit 1= 0 Bit 2=1 ,只有一次;(消息发送)
  • 非法Bit 1= 1 Bit 2=1 ,服务器认为非法,会关闭当前连接。
        目前 Bit[3-0]只在PUBLISH协议中使用有效 ,并且表中指明了是 MQTT 3.1.1/5.0版本 。对于其它 MQTT 协议版本,内容可能不同。所有固定头标记为" 保留 " 的协议类型, Bit[3-0] 必须保持与表中保持一致,如 SUBSCRIBE 协议,其Bit 1 必须为 1 如果接收方接收到非法的消息,会强行关闭当前连接。

3.1.3 MQTT消息QoS 

        MQTT发布 消息服务质量保证 QoS )不是端到端的,是客户端与服务器之间的。订阅者收到 MQTT 消息的
         QoS级别, 最终取决于发布消息的QoS和主题订阅的QoS 。( 标志位  0-2, 取最低标志位

  • Qos0:至多一次;(消息发送)

场景:如环境参数上报,一两次丢失不影响

  • QoS 1:至少一次;(消息发送)

禁用场景:如订单,付费等

  • QoS 2:只有一次;(消息发送)

Notity(Msg):通知上层应用消费消息

场景:如订单,付费等

3.1.4 PUBLISH 的 保留标识

  • Bit[0] 为 RETAIN字段,发布保留标识
  • Bit[0] = 1:表示服务器要保留这次推送的信息,如果有新的订阅者出现, 就把这消息推送给它,如果没有那么推送至当前订阅者后释放。

3.2 可变头(Variable Header

         可变头的意思是可变化的消息头部 有些报文类型包含可变头部,有些报文则不包含 。可变头部在固定头部和消息内容之间,其内容根据报文类型不同而不同。

3.2.1 协议名(protocol name

         协议名是表示协议名MQTT的UTF-8编码的字符串 MQTT 规范的后续版本不会改变这个字符串的偏移和长度。

         支持多种协议的服务端使用协议名字段判断数据是否为MQTT报文。协议名必须UTF-8字符串“MQTT”。如果服务端不愿意接受CONNECT但希望表明其MQTT服务端身份,可以发送包含原因码为0x84(不支持的协议版本)的CONNACK报文,然后必须关闭网络连接

3.2.2 协议版本 (protocol version

  • 8位无符号值表示客户端的版本等级。
  • 3.1.1版本的协议等级是4
  • MQTT v5.0的协议版本字段为50x05

3.2.3 MQTT会话(Clean Session)

        MQTT客户端向服务器发起 CONNECT 请求时,可以通过 ’Clean Session’ 标志设置会话。
  • ‘Clean Session’ 设置为 0,表示创建一个持久会话,在客户端断开连接时,会话仍然保持并保存离线消息,直到会话超时注销。
  • ‘Clean Session’ 设置为 1,表示创建一个新的临时会话,在客户端断开时,会话自动销毁。

3.2.4 Will Flag/Will Qos/Will Retain (遗言机制

        如果 Will Flag 被设置为 1 ,这意味着,如果连接请求被接受, 服务端必须存储一个Will Message ,并和网络连接关联起来。 之后在网络连接断开时候必须发布Will Message,除非服务端收到DISCONNECT包删掉了Will Message
        Will Message会在某些情况下发布,包括但不限于:
  • 服务端发现I/O错误或网络失败。
  • 客户端在Keep Alive时间内通信失败。
  • 客户端没有发送DISCONNECT包就关闭了网络连接。
  • 服务端因协议错误关闭了网络连接。

A. 如果 Will Flag 被设置为 1 ,连接标识中的 Will QoS Will Retain 字段将会被服务端用到
  • Will QoS 这两个bit表示发布Will Message时使用QoS的等级
  • Will Retain 这个bit表示Will Message在发布之后是否需要保留

B. Will Flag设置为0,那么Will Retain必须是0
C. Will Flag  设置为 1
  • 如果Will Retain设置为0,那么服务端必须发布Will Message,不必保存
  • 如果Will Retain设置为1,那么服务端必须发布Will Message,并保存

3.2.5 User Name Flag

  • 如果User Name Flag设置为0,那么用户名不必出现在载荷中
  • 如果User Name Flag设置为1,那么用户名必须出现在载荷中

3.2.6 Password Flag

  • 如果Password Flag设置为 0,那么密码不必出现在载荷中
  • 如果Password Flag设置为 1,那么密码必须出现在载荷中
  • 如果User Name Flag设置为 0,那么Password Flag必须设置为0

3.2.7 MQTT连接 保活心跳

KeepAlive:它指的是客户端从发送完成一个控制包到开始发送下一个的最大时间间隔。

A. 心跳的作用:PINGREQ包 (心跳包)

PINGREQ  包 从客户端发往服务端,可以用来:
  • 在没有其他控制包从客户端发送给服务端的时候,告知服务端客户端的存活状态
  • 请求服务端响应,来确认服务端是否存活
  • 确认网络连接的有效性

PINGRESP包从服务端发送给客户端来响应PINGREQ包。它代表服务端是存活的。

B. Keep Alive 保活周期

  • 通过KeepAlive参数设置保活周期
  • Keep Alive是以秒为单位的时间间隔
  • 用 2字节表示
        客户端可以在任何时间发送PINGREQ 包,不用关心 Keep Alive 的值,用 PINGRESP 来判断与服务端的网络连接是否正常。
        如果 Keep Alive 的值 非0 ,而且 服务端在1.5倍Keep Alive的周期内没有收到客户端的控制包 ,服务端必须作为网络故障 断开网络连接
        如果客户端在发送了PINGREQ 后,在一个合理的时间都没有收到 PINGRESP 包,客户端应该关闭和服务端的网络连接。
         Keep Alive 的值为 0 ,就关闭了维持的机制。这意味着,在这种情况下, 服务端不会断开静默的客户端

3.2.8 MQTT遗愿消息(Last Will)

         MQTT客户端向服务器端CONNECT请求时 可以设置是否发送遗愿消息(Will Message)标志 和遗愿消息主题(Topic)与内容(Payload)。
        MQTT客户端异常下线 ( 客户端断开前未向服务器发送 DISCONNECT 消息 ) MQTT 消息 服务器会发布遗愿消息

3.2.9 Message ID(Packet Identififier > 消息ID)

  • 包含2字节
  • 高字节在前,低字节在后。
  • 默认是从1开始并自增
  • ID被用完(消息被消费-)后,这个消息ID可以被重用
  • 客户端和服务端的消息ID是独立分配 , 客户端和服务端可以同时使用同一个消息ID
包含 Packet Identififier 的协议类型包括:
  • PUBLISH( QoS > 0 ):发布消息
  • PUBACK:发布确认(QoS1)
  • PUBREC:消息已接收(Qos2 第一阶段)
  • PUBREL:消息释放(QoS2 第二阶段)
  • PUBCOMP:发布结束(QoS2 第三阶段)
  • SUBSCRIBE:客户端订阅请求
  • SUBACK:服务端订阅确认
  • UNSUBSCRIBE:客户端取消订阅
  • UNSUBACK:服务端取消订阅确认

总结:ACK 表示消息被消费

        消息ID 默认是从 1 开始并自增,如果一个消息 ID 被用完后,这个消息 ID 可以被重用。对于 PUBLISH (QoS 1) 来 说,如果发送端接收到PUBACK ,那么这个消息 ID 就用完了。对于 PUBLISH(QoS 2) ,如果接收方收到 PUBCOMP , 那么这个消息ID 就用完了。对于 SUBSCRIBE UNSUBSCRIBE ,消息 ID 使用完成的标记是发送方收到了对应的SUBACK和 UNSUBACK
        另外客户端和服务端的消息ID 是独立分配的,客户端和服务端可以同时使用同一个消息 ID

3.3 消息体(Payload)

        Payload 意思是 消息载体 的意思
  • PUBLISH的Payload就是指消息内容(应用程序发布的消息内容)。
  • CONNECT的Payload则包含Client Identififier,Will TopicWill MessageUsernamePassword等信息。

包含 payload 的报文类型如下:
报文类型字段值描述
是否需要payload
保留0保留
-
CONNECT1客户端连接到服务器Required
CONNACK2连接确认None
PUBLISH3发布消息
Optional
PUBACK4发布确认(QoS1)
None
PUBREC5消息已接收(Qos2第一阶段)
None
PUBREL6消息释放(QoS2第二阶段)
None
PUBCOMP7发布结束(QoS2第三阶段)None
SUBSCRIBE8客户端订阅请求
Required
SUBACK9服务端订阅确认
Required
UNSUBACRIBE10客户端取消订阅
Required
UNSUBACK11服务端取消订阅确认Required
PINGREQ12客户端发送心跳
None
PINGRESP13服务端回复心跳
None
DISCONNECT14客户端断开连接请求
None
AUTH(V5.0使用)15认证数据交换

-

        总结
        我们介绍了MQTT 协议的消息格式, MQTT消息格式包含Fixed Header, Variable Header和Payload 。 因为MQTT 消息格式非常精简,所以可以高效的传输数据。
        Fixed Header中包含首字节,高 4 位用来表示报文类型,低 4 位用于类型控制。 目前只有PUBLISH使用了类型控制字段 。其它控制字段被保留并且必须与协议定义保持一致。
        Fixed Header同时包含 Remaining Length ,这是剩余消息长度,最大长度为 4 字节,理论上一条 MQTT 最大可以传输256MB数据。Remaining Length=Variable Header+Payload长度
        Variable Header是可变头部,有些报文类型中需要包含可变头部,可变头部根据报文类型不同而不同。比如 Packet Identififier在发布,订阅 / 取消订阅等报文中都使用到。
        Payload是消息内容,也只在某些报文类型中出现,其内容和格式也根据报文类型不同而不同。
  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ladymorgana

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值