02.报文协议

MQTT 协议原理

MQTT 3(当前版本 3.1.1)是目前使用的最为广泛的 MQTT 协议标准。尽管 MQTT5 标准已经发布,并且带来了一些令人振奋的新特性,但是在整个应用场景上,从后台服务到消息中间件再到客户端 SDK 等环节上的产品升级并没有都完成,再加上既有部署的维护,业界从版本 3 到 5 的过渡可能会持续相当长一段时间。

在一个 MQTT 协议中有三个角色会参与到整个通信过程,发布者(publisher)、代理(broker)和订阅者(subscriber)。有别于传统的客户端/服务器通讯协议,MQTT 协议并不是端到端的,消息传递通过代理,包括会话(session)也不是建立在发布者和订阅者之间,而是建立在端和代理之间。代理解除了发布者和订阅者之间的耦合。除了发布者和订阅者之间传递普通消息,代理还可以为发布者处理保留消息和遗愿消息,并可以更改服务质量(QoS)等级。

MQTT 控制报文

MQTT 协议工作在 TCP 之上,端和代理之间通过交换预先定义的控制报文来完成通信。MQTT 报文有 3 个部分组成,并按下表顺序出现:

固定报头(fixed header) 可变报头(variable header) 荷载(payload)
所有报文都包含 部分报文包含 部分报文包含
  • 固定头(Fixed header):存在于所有的 MQTT 数据包中,用于表示数据包类型及对应标志、数据包大小等;
  • 可变头(Variable header):存在于部分类型的 MQTT 数据包中,具体内容是由相应类型的数据包决定的;
  • 消息体(Payload):存在于部分的 MQTT 数据包中,存储消息的具体数据。

固定头

固定头格式

固定头的第一个字节的高 4 位 Bit 用于表示该数据包的类型。MQTT 的数据包有以下一些类型:

名称值方向描述 Reserved0 不可用保留位 CONNECT1Client 到 BrokerClient 请求连接到 BrokerCONNACK2Broker 到 Client 连接确认 PUBLISH3 双向发布消息 PUBACK4 双向发布确认 PUBREC5 双向发布收到 PUBREL6 双向发布释放 PUBCOMP7 双向发布完成 SUBSCRIBE8Client 到 BrokerClient 请求订阅 SUBACK9Broker 到 Client 订阅确认 UNSUBSCRIBE10Client 到 BrokerClient 请求取消订阅 UNSUBACK11Broker 到 Client 取消订阅确认 PINGREQ12Client 到 BrokerPING 请求 PINGRESP13Broker 到 ClientPING 应答 DISCONNECT14Client 到 BrokerClient 主动中断连接 Reserved15 不可用保留位

低 4 位 Bit 则用于表示数据包的 Flag,不同的数据包类型,Flag 的定义不同,每种数据包对应的 Flag 如下:

数据包标识位 Bit 3Bit 2Bit 1Bit 0CONNECT 保留位 0000CONNACK 保留位 0000PUBLISHMQTT 3.1.1 使用 DUPQoSQoSRETAINPUBACK 保留位 0000PUBREC 保留位 0000PUBREL 保留位 0000PUBCOMP 保留位 0000SUBSCRIBE 保留位 0000SUBACK 保留位 0000UNSUBSCRIBE 保留位 0000UNSUBACK 保留位 0000PINGREQ 保留位 0000PINGRESP 保留位 0000DISCONNECT 保留位 0000

从固定头的第 2 字节开始是用于表示 MQTT 数据包剩余长度的字段,最少一个字节,最大四个字节。每一个字节的低 7 位用于标识值,范围为 0~127。最高的 1 位是标识位,用来说明是否有后续字节来标识长度。标识为 0,代表没有后续字节;标识为 1,代表后续还有一个字节用于标识包的长度。MQTT 协议相应字节数对应的最小、最大包长度如下表所示:

字节数最小包长度(除固定头外)最大包长度(除固定头外)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)。可知 MQTT 协议中数据包(除固定头外)的最大长度为 268435455 字节,约 256M。

报文种类

1.连接请求(CONNECT):当一个从客户端到服务器的 TCP/IP 套接字连接被建立时,必须用一个连接流来创建一个协议级别的会话。

2.连接请求确认(CONNECTACK):连接请求确认报文(CONNECTACK)是服务器发给客户端,用以确认客户端的连接请求

3.发布报文(PUBLISH):客户端发布报文到服务器端,用来提供给有着不同需求的订阅者们。每个发布的报文都有一个主题,这是一个分层的命名空间,他定义了报文来源分类,方便订阅者订阅他们需要的主题。订阅者们可以注册自己的需要的报文类别。

4.发布确认报文(PUBACK):发布确认报文(PUBACK)是对服务质量级别为 1 的发布报文的应答。他可以是服务器对发布报文的客户端的报文确认,也可以是报文订阅者对发布报文的服务器的应答。

5.发布确认报文(PUBREC):PUBREC 报文是对服务质量级别为 2 的发布报文的应答。这是服务质量级别为 2 的协议流的第二个报文。PUBREC 是由服务器端对发布报文的客户端的应答,或者是报文订阅者对发布报文的服务器的应答。

6.发布确认报文(PUBREL):PUBREL 是报文发布者对来自服务器的 PUBREC 报文的确认,或者是服务器对来自报文订阅者的 PUBREC 报文的确认。它是服务质量级别为 2 的协议流的第三个报文。

7.确定发布完成(PUBCOMP):PUBCOMP 报文是服务器对报文发布者的 PUBREL 报文的应答,或者是报文订阅者对服务器的 PUBREL 报文的应答。它是服务质量级别为 2 的协议流的第四个也是最后一个报文。

8.订阅命名的主题(SUBSCRIBE):订阅报文(SUBSCRIBE)允许一个客户端在服务器上注册一个或多个感兴趣的主题名字。发布给这些主题的报文作为发布报文从服务器端交付给客户端。订阅报文也描述了订阅者想要收到的发布报文的服务质量等级。

9.订阅报文确认(SUBACK):当服务器收到客户端发来的订阅报文时,将发送订阅报文的确认报文给客户端。一个这样的确认报文包含一列被授予的服务质量等级。被授予的服务质量等级次序和对应的订阅报文中的主题名称的次序相符。

10.退订命名的主题(UNSUBSCRIBE):退订主题的报文是从客户端发往服务器端,用以退订命名的主题。

11.退订确认(UNSUBACK):退订确认报文是从服务器发往客户端,用以确认客户端发来的退订请求报文。

12.Ping 请求(PINGREQ)

Ping 请求报文是从连接的客户端发往服务器端,用来询问服务器端是否还存在。

13.Ping 应答(PINGRESP):Ping 应答报文是从服务器端发往 Ping 请求的客户端,对客户端的 Ping 请求进行确认。

14.断开通知(DISCONNECT):断开通知报文是从客户端发往服务器端用来指明将要关闭它的 TCP/IP 连接,他允许彻底地断开,而非只是下线。如果客户端已经和干净会话标志集联系,那么所有先前关于客户端维护的信息将被丢弃。一个服务器在收到断开报文之后,不能依赖客户端关闭 TCP/IP 连接。

可变头

可变报文头主要包含协议名、协议版本、连接标志(Connect Flags)、心跳间隔时间(Keep Alive timer)、连接返回码(Connect Return Code)、主题名(Topic Name)等,后面会针对此部分进行具体讲解。

消息体

当 MQTT 发送的消息类型是 CONNECT(连接)、PUBLISH(发布)、SUBSCRIBE(订阅)、SUBACK(订阅确认)、UNSUBSCRIBE(取消订阅)时,则会带有负荷。

上一页
下一页