MQTT 5.0 报文解析 01:CONNECT 与 CONNACK

本文涉及的产品
注册配置 MSE Nacos/ZooKeeper,118元/月
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
性能测试 PTS,5000VUM额度
简介: 如果我们想要使用 MQTT 进行通信,第一步必然是建立一个 MQTT 连接,而建立 MQTT 连接需要用到两个控制报文,它们分别是 CONNECT 报文与 CONNACK 报文。CONNECT 报文是客户端与服务端建立网络连接后,向服务端发送的第一个控制报文,用来发起连接请求。服务端将返回 CONNACK 报文告知客户端连接结果。

MQTT 5.0 报文介绍 中,我们介绍了 MQTT 报文由固定报头、可变报头和有效载荷三个部分组成,以及可变字节整数、属性这类 MQTT 报文中的通用概念。现在,我们将按照实际的用途来进一步介绍各个类型的报文的组成。首先,我们将专注于用于建立 MQTT 连接的报文。

如果我们想要使用 MQTT 进行通信,第一步必然是建立一个 MQTT 连接,而建立 MQTT 连接需要用到两个控制报文,它们分别是 CONNECT 报文与 CONNACK 报文。CONNECT 报文是客户端与服务端建立网络连接后,向服务端发送的第一个控制报文,用来发起连接请求。服务端将返回 CONNACK 报文告知客户端连接结果。

报文示例

我们使用 MQTTX CLI公共 MQTT 服务器 发起一个连接,在这个连接中,我们将协议版本设置 MQTT 5.0,Clean Start 设置为 1,Session Expiry Interval 设置为 300 秒,Keep Alive 设置为 60,用户名和密码分别设置为 admin 和 public,对应的 MQTTX CLI 命令为:

mqttx conn --hostname broker.emqx.io --mqtt-version 5 \  --session-expiry-interval 300 --keepalive 60 --username admin --password public

以下是使用 Wireshark 工具抓取到的 MQTTX CLI 发出的 CONNECT 报文,Linux 环境可以先使用 tcpdump 命令抓取报文,然后再导入至 Wireshark 查看:

10 2f 00 04 4d 51 54 54 05 c2 00 3c 05 11 00 00 01 2c 00 0e 6d 71 74 74 78 5f 30 63 36 36 38 64 30 64 00 05 61 64 6d 69 6e 00 06 70 75 62 6c 69 63

但这是一串不易理解的十六进制字节,除非它们被转换成以下格式:

01connectpacket.png

同样我们也抓取到了公共 MQTT 服务器返回的 CONNACK 报文:

20 13 00 00 10 27 00 10 00 00 25 01 2a 01 29 01 22 ff ff 28 01

在解析这串报文数据之后我们可以看到,CONNACK 报文的 Reason Code 为 0,表示连接成功,后面的多个属性则给出了服务器支持的功能列表,比如支持的最大报文长度,是否支持保留消息等等:

02connackpacket.png

当然,Wireshark 其实也已经为我们列出了报文中各个字段的值,通过下文对 CONNECT 和 CONNACK 报文结构的介绍,再结合 Wireshark 的抓包结果按图索骥,你将很快掌握这两个报文:

03wireshark.png

CONNECT 报文结构

固定报头

CONNECT 报文的固定报头中,位于首字节高 4 位的报文类型字段的值必须为 1(0b0001),首字节中低 4 位则固定全为 0。

所以,CONNECT 报文的第一个字节的值必然为 0x10,我们可以以此来判断某个报文是否为 CONNECT 报文。

MQTT CONNECT 固定报头

可变报头

CONNECT 报文的可变报头按顺序包含以下字段:

MQTT CONNECT 可变报头

  • Protocol Name:这是一个 UTF-8 编码的字符串,用来表示协议名称。在 MQTT 中,UTF-8 编码的字符串的前两个字节统一用于指示后面实际的字符数据的长度。MQTT 3.1.1 和 MQTT 5.0 中协议名称固定为 MQTT,所以对应的以十六进制字节表示的完整内容就是 00 04 4d 51 54 54,其中 4d 51 54 54 就是 MQTT 这个字符串对应的 ASCII 值。最早的 MQTT 3.1 中的协议名称是 MQIsdp,所以它对应的是 00 06 4d 51 49 73 64 70

  • Protocol Version:这是一个单个字节长度的无符号整数,用来表示协议版本。目前只有三个可取值,3 表示 MQTT 3.1,4 表示 MQTT 3.1.1,5 表示 MQTT 5.0。

  • Connect Flags:连接标识,它只有一个字节,但包含了多个用于控制连接行为或指示有效载荷中某些字段是否存在的参数。

    MQTT Connect Flags

    • User Name Flag:用于指示有效载荷是否包含用户名字段。

    • Password Flag:用于指示有效载荷是否包含密码字段。

    • Will Retain:用于指示遗嘱消息是否为保留消息。

    • Will QoS:用于指示遗嘱消息的 QoS。

    • Will Flag:用于指示有效载荷是否包含了遗嘱消息的相关字段。

    • Clean Start:用于指示当前连接是一个新的会话还是一个已存在会话的延续,这决定了服务端将直接新建会话还是尝试复用已存在的会话。

    • Reserved:这是一个保留位,它的值必须为 0。

  • Keep Alive:这是一个双字节长度的无符号整数,用来表示客户端发送两个相邻的控制报文的最大时间间隔。

  • Properties:下表列出了 CONNECT 报文的所有可用属性。

Identifier Property Name Type
0x11 Session Expiry Interval 四字节整数
0x21 Receive Maximum 双字节整数
0x27 Maximum Packet Size 四字节整数
0x22 Topic Alias Maximum 双字节整数
0x19 Request Response Information 单字节
0x17 Request Problem Information 单字节
0x26 User Property UTF-8 字符串对
0x15 Authentication Method UTF-8 编码的字符串
0x16 Authentication Data 二进制数据

有效载荷

CONNECT 报文有效载荷中的字段,除了 Client ID 以外,其他字段都是可选的,它们是否存在取决于可变报头的 Connect Flags 中对应标志位的值。但如果这些存在,就必须按照 Client ID、Will Properties、Will Topic、Will Payload、User Name、Password 的顺序出现。

MQTT 有效载荷

CONNACK 报文结构

固定报文

固定报头中首字节的高 4 位值为 2(0b0010),表示这是一个 CONNACK 报文。

MQTT CONNACK 固定报文

可变报头

CONNACK 报文的可变报头按顺序包含以下字段:

MQTT CONNACK 可变报头

  • Connect Acknowledge Flags:连接确认标志。

    • Reserved (Bit 7 - 1):保留位,必须设置为 0.

    • Session Present (Bit 0):用于指示服务端是否正在使用已存在的会话与客户端恢复通信。仅在客户端在 CONNECT 连接中将 Clean Start 设置为 0 时,Session Present 可能为 1。

  • Reason Code:用于指示连接结果。下表列出了一些在 CONNACK 报文中常见的 Reason Code,完整列表可参阅 MQTT 5.0 Reason Code 速查表

Value Reason Code Name Description
0x00 Success 连接被接受。
0x81 Malformed Packet 服务端无法按照协议规范正确解析 CONNECT 报文,例如保留位没有按照协议要求设置为 0。
0x82 Protocol Error CONNECT 报文可以被正确解析,但是内容不符合协议规范,比如 Will Topic 字段的值不是一个合法的 MQTT 主题。
0x84 Unsupported Protocol Version 服务端不支持客户端所请求的 MQTT 协议版本。
0x85 Client Identifier not valid 表示 Client ID 是有效的字符串,但是不被服务端接受,比如 Client ID 超出了服务端允许的最大长度。
0x86 Bad User Name or Password 客户端因为使用了错误的用户名或密码而被拒绝连接。
0x95 Packet too large CONNECT 报文超过了服务端允许的最大长度,可能是因为携带了较大的遗嘱消息。
0x8A Banned 表示客户端被禁止登录。例如服务端检测到客户端的异常连接行为,所以将这个客户端的 Client ID 或者 IP 地址加入到了黑名单列表中,又或者是后台管理人员手动封禁了这个客户端,当然以上这些通常需要视服务端的具体实现而定。
  • Properties:下表列出了 CONNACK 报文的所有可用属性。
Identifier Property Name Type
0x11 Session Expiry Interval 四字节整数
0x21 Receive Maximum 双字节整数
0x24 Maximum QoS 单字节
0x25 Retain Available 单字节
0x27 Maximum Packet Size 四字节整数
0x12 Assigned Client Identifier UTF-8 编码的字符串
0x22 Topic Alias Maximum 双字节整数
0x1F Reason String UTF-8 编码的字符串
0x26 User Property UTF-8 字符串对
0x28 Wildcard Subscription Available 单字节
0x29 Subscription Identifier Available 单字节
0x2A Shared Subscription Available 单字节
0x13 Server Keep Alive 双字节整数
0x1A Response Information UTF-8 编码的字符串
0x1C Server Reference UTF-8 编码的字符串
0x15 Authentication Method UTF-8 编码的字符串
0x16 Authentication Data 二进制数据

有效载荷

CONNACK 报文不包含有效载荷。

总结

CONNECT 是客户端与服务端的网络连接建立后,客户端发送的第一个 MQTT 报文,CONNACK 作为 CONNECT 的响应报文通过原因码来指示连接结果。

客户端和服务端需要借助 CONNECT 和 CONNACK 报文来完成必要信息的交换,例如客户端使用的协议版本、Client ID、用户名、密码,以及服务端是否存在相应的会话、支持的最大报文长度和最大 QoS 等级等等。

以上就是对 MQTT CONNECT 和 CONNACK 报文的介绍,在后续的文章中,我们还会继续研究 PUBLISH、DISCONNECT 这些报文的结构和组成。

相关实践学习
消息队列RocketMQ版:基础消息收发功能体验
本实验场景介绍消息队列RocketMQ版的基础消息收发功能,涵盖实例创建、Topic、Group资源创建以及消息收发体验等基础功能模块。
消息队列 MNS 入门课程
1、消息队列MNS简介 本节课介绍消息队列的MNS的基础概念 2、消息队列MNS特性 本节课介绍消息队列的MNS的主要特性 3、MNS的最佳实践及场景应用 本节课介绍消息队列的MNS的最佳实践及场景应用案例 4、手把手系列:消息队列MNS实操讲 本节课介绍消息队列的MNS的实际操作演示 5、动手实验:基于MNS,0基础轻松构建 Web Client 本节课带您一起基于MNS,0基础轻松构建 Web Client
目录
相关文章
|
2月前
|
消息中间件 Java Apache
RocketMQ消息回溯实践与解析
在分布式系统和高并发应用的开发中,消息队列扮演着至关重要的角色,而RocketMQ作为阿里巴巴开源的一款高性能消息中间件,以其高吞吐量、高可用性和灵活的配置能力,在业界得到了广泛应用。本文将围绕RocketMQ的消息回溯功能进行实践与解析,分享工作学习中的技术干货。
72 3
|
23天前
|
消息中间件 存储 监控
RocketMQ消息重试机制解析!
RocketMQ消息重试机制解析!
RocketMQ消息重试机制解析!
EMQ
|
6月前
|
运维 Linux 网络性能优化
MQTT 5.0 报文解析 05:DISCONNECT
在 MQTT 中,客户端和服务端可以在断开网络连接前向对端发送一个 DISCONNECT 报文,来指示连接关闭的原因。客户端发送的 DISCONNECT 报文还可以影响服务端在连接断开后的行为,例如是否发送遗嘱消息,是否更新会话过期间隔。
EMQ
121 0
MQTT 5.0 报文解析 05:DISCONNECT
|
3月前
|
消息中间件 开发者
【RabbitMQ深度解析】Topic交换器与模式匹配:掌握消息路由的艺术!
【8月更文挑战第24天】在消息队列(MQ)体系中,交换器作为核心组件之一负责消息路由。特别是`topic`类型的交换器,它通过模式匹配实现消息的精准分发,适用于发布-订阅模式。不同于直接交换器和扇形交换器,`topic`交换器支持更复杂的路由策略,通过带有通配符(如 * 和 #)的模式字符串来定义队列与交换器间的绑定关系。
55 2
|
3月前
|
消息中间件 Java RocketMQ
微服务架构师的福音:深度解析Spring Cloud RocketMQ,打造高可靠消息驱动系统的不二之选!
【8月更文挑战第29天】Spring Cloud RocketMQ结合了Spring Cloud生态与RocketMQ消息中间件的优势,简化了RocketMQ在微服务中的集成,使开发者能更专注业务逻辑。通过配置依赖和连接信息,可轻松搭建消息生产和消费流程,支持消息过滤、转换及分布式事务等功能,确保微服务间解耦的同时,提升了系统的稳定性和效率。掌握其应用,有助于构建复杂分布式系统。
61 0
EMQ
|
5月前
|
安全 开发工具 数据安全/隐私保护
MQTT 5.0 报文解析 06:AUTH
MQTT 5.0 引入了增强认证特性,它使 MQTT 除了简单密码认证和 Token 认证以外,还能够支持质询/响应风格的认证。为了实现这一点,它在原先 CONNECT 和 CONNACK 报文的基础上,又引入了 AUTH 报文来实现任意多次的认证数据交换,以支持各种不同类型的认证机制,例如 SCRAM、Kerberos 认证等等。
EMQ
279 7
MQTT 5.0 报文解析 06:AUTH
|
4月前
|
网络协议 安全 网络安全
解析IPv6报文结构
【7月更文挑战第1天】IPv6报文结构包括基本头和可选的扩展头,基本头固定40字节,含8个字段,不支持分片,提升了处理效率。扩展头灵活处理选项,长度为8字节的倍数,可包含如路由、分片、认证和安全封装等信息。多个扩展头按特定顺序排列,目的选项头可出现两次。
|
5月前
|
消息中间件 存储 运维
RocketMQ与Kafka深度对比:特性与适用场景解析
RocketMQ与Kafka深度对比:特性与适用场景解析
|
5月前
|
消息中间件 自然语言处理 负载均衡
RabbitMQ揭秘:轻量级消息队列的优缺点全解析
**RabbitMQ简介** RabbitMQ是源自电信行业的消息中间件,支持AMQP协议,提供轻量、快速且易于部署的解决方案。它拥有灵活的路由配置,广泛的语言支持,适用于异步处理、负载均衡、日志收集和微服务通信等场景。然而,当面临大量消息堆积或高吞吐量需求时,性能可能会下降,并且扩展和开发成本相对较高。
263 0
|
5天前
|
消息中间件 存储 Kafka
MQ 消息队列核心原理,12 条最全面总结!
本文总结了消息队列的12个核心原理,涵盖消息顺序性、ACK机制、持久化及高可用性等内容。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。

相关产品

  • 云消息队列 MQ
  • 推荐镜像

    更多