MQTT 5.0 报文解析 05:DISCONNECT

简介: 在 MQTT 中,客户端和服务端可以在断开网络连接前向对端发送一个 DISCONNECT 报文,来指示连接关闭的原因。客户端发送的 DISCONNECT 报文还可以影响服务端在连接断开后的行为,例如是否发送遗嘱消息,是否更新会话过期间隔。

欢迎阅读 MQTT 5.0 报文系列的第五篇文章。在上一篇中,我们已经介绍了 MQTT 5.0 的 PINGREQ 和 PINGRESP 报文。现在,我们将介绍下一个控制报文:DISCONNECT。

在 MQTT 中,客户端和服务端可以在断开网络连接前向对端发送一个 DISCONNECT 报文,来指示连接关闭的原因。客户端发送的 DISCONNECT 报文还可以影响服务端在连接断开后的行为,例如是否发送遗嘱消息,是否更新会话过期间隔。

DISCONNECT 报文示例

我们使用 MQTTX CLI向公共 MQTT 服务器发起一个指定了 Client ID 的客户端连接,并将 --reconnect-period 设置为 0 来禁用自动重连,然后在另一个终端中运行相同的命令创建一个使用相同 Client ID 的连接。

整个过程使用 Wireshark 工具来抓取在客户端与服务器之间往返的 MQTT 报文,Linux 环境可以使用 tcpdump 命令抓取报文,然后导入至 Wireshark 分析。

以下命令将创建一个 Client ID 为 mqtt-892324 的客户端连接,为了避免 Client ID 与别人重复,建议将它改为其他随机字符串:

mqttx conn --hostname broker.emqx.io --mqtt-version 5 --client-id mqtt-892324 \ --reconnect-period 0

在我们发起第二个连接后,Wireshark 将捕获到公共 MQTT 服务器返回给第一个连接的 DISCONNECT 报文:

e0 02 8e 00

这四个十六进制字节,对应着以下报文内容:

DISCONNECT Packet.png

通过下文对 DISCONNECT 报文结构的介绍,你将了解到如何从原始的报文数据中提取你想要的信息。

DISCONNECT 报文结构

固定报头

固定报头首字节的高 4 位,即报文类型字段的值为 14(0b1110),低 4 位全部为 0,表示这是一个 DISCONNECT 报文。

Fixed Header.png

可变报头

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

Viriable Header.png

  • 原因码(Reason Code):一个单字节的无符号整数,用于向对端指示连接断开的原因。下表列出了在 DISCONNECT 报文中常见的 Reason Code,完整列表可参阅 MQTT 5.0 Reason Code 速查表。
Value Reason Code Name Sent By Description
0x00 Normal disconnection 客户端、服务端 表示连接正常关闭,因此服务端不会发布遗嘱消息。
0x04 Disconnect with Will Message 客户端 连接正常关闭,但客户端希望服务端仍然发布遗嘱消息。
0x81 Malformed Packet 客户端、服务端 表示收到了无法按照协议规范正确解析的控制报文,在 MQTT 中我们将这类报文称为畸形报文。
0x82 Protocol Error 客户端、服务端 协议错误通常指控制报文在按照协议规范解析以后才能发现的错误,包括包含协议不允许的数据、行为与协议要求不符等等。比如客户端在一个连接内发送了两个 CONNECT 报文。
0x8D Keep Alive timeout 服务端 服务端在超过 1.5 倍的 Keep Alive 时间内没有收到任何报文,因此关闭了连接。
0x8E Session taken over 服务端 另一个更新的使用了且相同的 Client ID 的连接被建立,导致服务端关闭了此连接。
0x93 Receive Maximum exceeded 客户端、服务端 表示对端同时发送的 QoS > 0 的 PUBLISH 报文数量超过了连接时设置的接收最大值。
0x94 Topic Alias invalid 客户端、服务端 表示主题别名不合法。比如 PUBLISH 报文中的主题别名值为 0 或者大于连接时约定的最大主题别名。
0x95 Packet too large 客户端、服务端 表示报文超过了连接时约定的最大允许长度。
0x98 Administrative action 客户端、服务端 表示连接因为管理操作而被关闭,比如运维人员在服务端后台踢除了客户端连接。
0x9C Use another server 服务端 表示客户端应该临时切换到另一个服务器。如果另一个服务器不是客户端已知的,那么还需要配合 Server Reference 属性一起使用,以告知客户端新的服务端的地址。
0x9D Server moved 服务端 表示客户端应该永久切换到另一个服务器。如果另一个服务器不是客户端已知的,那么还需要配合 Server Reference 属性一起使用,以告知客户端新的服务端的地址。
  • 属性(Properties):下表列出了 DISCONNECT 报文的所有可用属性。
Identifier Property Name Sent By Type
0x11 Session Expiry Interval 客户端 四字节整数
0x1F Reason String 客户端、服务端 UTF-8 编码的字符串
0x26 User Property 客户端、服务端 UTF-8 字符串对
0x1C Server Reference 服务端 UTF-8 编码的字符串

与之前介绍的其他报文不同,客户端和服务端在 DISCONNECT 报文中可以使用的原因码和属性是不同的,例如 Session Expiry Interval 属性就只能在客户端发送的 DISCONNECT 报文中使用,所以我们在上面的列表中均列出了它们的可用范围。

有效载荷

DISCONNECT 报文不包含有效载荷。

总结

客户端和服务端都可以发送 DISCONNECT 报文,表示准备断开网络连接,报文中的原因码可以向接收方指示连接关闭的原因。当 MQTT 连接意外断开时,我们可以优先查看是否收到了 DISCONNECT 报文以及报文中原因码的值。

虽然客户端和服务端在 DISCONNECT 报文中可以用的原因码和属性存在差异,但我们并不需要强行去记忆它们。它们通常都和对应的机制与行为相关,例如遗嘱消息只会由服务端发布,所以希望连接正常关闭但对端仍要发布遗嘱消息的原因码 0x04,也会被客户端使用。

以上就是对 DISCONNECT 报文的介绍,在下一篇文章中我们将介绍 MQTT 5.0 增强认证特性所使用的 AUTH 报文,它也是 MQTT 中最后一个报文类型。

相关实践学习
RocketMQ一站式入门使用
从源码编译、部署broker、部署namesrv,使用java客户端首发消息等一站式入门RocketMQ。
消息队列 MNS 入门课程
1、消息队列MNS简介 本节课介绍消息队列的MNS的基础概念 2、消息队列MNS特性 本节课介绍消息队列的MNS的主要特性 3、MNS的最佳实践及场景应用 本节课介绍消息队列的MNS的最佳实践及场景应用案例 4、手把手系列:消息队列MNS实操讲 本节课介绍消息队列的MNS的实际操作演示 5、动手实验:基于MNS,0基础轻松构建 Web Client 本节课带您一起基于MNS,0基础轻松构建 Web Client
目录
相关文章
EMQ
|
18天前
|
安全 开发工具 数据安全/隐私保护
MQTT 5.0 报文解析 06:AUTH
MQTT 5.0 引入了增强认证特性,它使 MQTT 除了简单密码认证和 Token 认证以外,还能够支持质询/响应风格的认证。为了实现这一点,它在原先 CONNECT 和 CONNACK 报文的基础上,又引入了 AUTH 报文来实现任意多次的认证数据交换,以支持各种不同类型的认证机制,例如 SCRAM、Kerberos 认证等等。
EMQ
228 2
MQTT 5.0 报文解析 06:AUTH
|
7天前
|
消息中间件 自然语言处理 负载均衡
RabbitMQ揭秘:轻量级消息队列的优缺点全解析
**RabbitMQ简介** RabbitMQ是源自电信行业的消息中间件,支持AMQP协议,提供轻量、快速且易于部署的解决方案。它拥有灵活的路由配置,广泛的语言支持,适用于异步处理、负载均衡、日志收集和微服务通信等场景。然而,当面临大量消息堆积或高吞吐量需求时,性能可能会下降,并且扩展和开发成本相对较高。
23 0
EMQ
|
1月前
|
开发工具
MQTT 5.0 报文解析 04:PINGREQ 与 PINGRESP
除了用于连接、发布和订阅的控制报文,MQTT 还有一类报文用于在客户端和服务端之间模拟心跳,以达到保持连接的目的,它们分别是 PINGREQ 报文和 PINGRESP 报文,我们通常也会称它们为心跳报文。
EMQ
151 0
MQTT 5.0 报文解析 04:PINGREQ 与 PINGRESP
|
6天前
|
消息中间件 Java 双11
RocketMQ:揭秘电商巨头背后的消息队列秘密
**RocketMQ概览:**高性能分布式消息队列,适用于有序消息、事务处理、流计算、消息推送、日志处理及Binlog分发。在双11等高流量场景下证明了其性能、稳定性和低延迟。Java开发,利于扩展,性能超RabbitMQ,支持死信队列,但可能有集成兼容性问题。适合Java开发者,为电商等场景优化,每秒处理大量消息。
27 3
RocketMQ:揭秘电商巨头背后的消息队列秘密
|
13天前
|
消息中间件 监控 应用服务中间件
消息队列 MQ操作报错合集之重启Broker后,积压数出现为负数是什么导致的
在使用消息队列MQ时,可能会遇到各种报错情况。以下是一些常见的错误场景、可能的原因以及解决建议的汇总:1.连接错误、2.消息发送失败、3.消息消费报错、4.消息重试与死信处理、5.资源与权限问题、6.配置错误、7.系统资源限制、8.版本兼容性问题。
消息队列 MQ操作报错合集之重启Broker后,积压数出现为负数是什么导致的
|
13天前
|
消息中间件 Java 测试技术
消息队列 MQ操作报错合集之设置了setKeepAliveInterval(1)但仍然出现客户端未连接,该怎么解决
在使用消息队列MQ时,可能会遇到各种报错情况。以下是一些常见的错误场景、可能的原因以及解决建议的汇总:1.连接错误、2.消息发送失败、3.消息消费报错、4.消息重试与死信处理、5.资源与权限问题、6.配置错误、7.系统资源限制、8.版本兼容性问题。
|
13天前
|
消息中间件 设计模式 网络安全
消息队列 MQ操作报错合集之broker启用controller配置时,遇到报错,是什么导致的
在使用消息队列MQ时,可能会遇到各种报错情况。以下是一些常见的错误场景、可能的原因以及解决建议的汇总:1.连接错误、2.消息发送失败、3.消息消费报错、4.消息重试与死信处理、5.资源与权限问题、6.配置错误、7.系统资源限制、8.版本兼容性问题。
|
13天前
|
消息中间件 Apache RocketMQ
消息队列 MQ操作报错合集之设置了controller后,有一主一从,但只显示一个,该怎么解决
在使用消息队列MQ时,可能会遇到各种报错情况。以下是一些常见的错误场景、可能的原因以及解决建议的汇总:1.连接错误、2.消息发送失败、3.消息消费报错、4.消息重试与死信处理、5.资源与权限问题、6.配置错误、7.系统资源限制、8.版本兼容性问题。
|
13天前
|
消息中间件 测试技术 Apache
消息队列 MQ产品使用合集之在测试环境中拥有大量的topic会有什么影响
阿里云消息队列MQ(Message Queue)是一种高可用、高性能的消息中间件服务,它允许您在分布式应用的不同组件之间异步传递消息,从而实现系统解耦、流量削峰填谷以及提高系统的可扩展性和灵活性。以下是使用阿里云消息队列MQ产品的关键点和最佳实践合集。
|
13天前
|
消息中间件 存储 网络性能优化
消息队列 MQ产品使用合集之一个设备的离线消息的数量限制是多少
阿里云消息队列MQ(Message Queue)是一种高可用、高性能的消息中间件服务,它允许您在分布式应用的不同组件之间异步传递消息,从而实现系统解耦、流量削峰填谷以及提高系统的可扩展性和灵活性。以下是使用阿里云消息队列MQ产品的关键点和最佳实践合集。

热门文章

最新文章

推荐镜像

更多