前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MQTT 5.0 报文解析 05:DISCONNECT

MQTT 5.0 报文解析 05:DISCONNECT

原创
作者头像
EMQ映云科技
发布2024-05-29 18:30:04
1720
发布2024-05-29 18:30:04

欢迎阅读 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 与别人重复,建议将它改为其他随机字符串:

代码语言:mqtt
复制
mqttx conn --hostname broker.emqx.io --mqtt-version 5 --client-id mqtt-892324 \ --reconnect-period 0

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

代码语言:mqtt
复制
e0 02 8e 00

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

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

DISCONNECT 报文结构

固定报头

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

可变报头

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

  • 原因码(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 中最后一个报文类型。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • DISCONNECT 报文示例
  • DISCONNECT 报文结构
    • 固定报头
      • 可变报头
        • 有效载荷
        • 总结
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档