DISCONNECT报文是客户端发给服务端的最后一个MQTT控制报文。表示客户端为什么断开网络连接的原因。客户端和服务端在关闭网络连接之前可以发送一个DISCONNECT报文。如果在客户端没有首先发送包含原因码为0x00(正常断开)DISCONNECT报文并且连接包含遗嘱消息的情况下,遗嘱消息会被发布。更多细节,参考3.1.2.5节。
服务端不能发送DISCONNECT报文,直到它发送了包含原因码小于0x80的CONNACK报文之后 [MQTT-3.14.0-1]。
Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
byte 1 | MQTT控制报文类型 (14) | 保留位 | ||||||
1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | |
byte 2 | 剩余长度 |
服务端或客户端必须验证所有的保留位都被设置为0,如果他们不为0,发送包含原因码为0x81(无效报文)的DISCONNECT报文,如4.13节所述 [MQTT-3.14.1-1]。
剩余长度字段
等于可变报头的长度,编码为变长字节整数。
DISCONNECT报文的可变报头按顺序包含以下字段:断开原因码,属性(Properties)。属性的编码规则如2.2.2节所述。
可变报头的第1个字节是断开原因码。如果剩余长度小于1,则表示使用原因码0x00(正常断开)。
单字节无符号断开原因码字段如下所示。
表 3-10 – 断开原因值 Disconnect Reason Code
值 | 16进制 | 原因码名称 | 发送端 | 说明 |
---|---|---|---|---|
0 | 0x00 | 正常断开 | 客户端或服务端 | 正常关闭连接。不发送遗嘱。 |
4 | 0x04 | 包含遗嘱消息的断开 | 客户端 | 客户端希望断开但也需要服务端发布它的遗嘱消息。 |
128 | 0x80 | 未指定错误 | 客户端或服务端 | 连接被关闭,但发送端不愿意透露原因,或者没有其他适用的原因码。 |
129 | 0x81 | 无效的报文 | 客户端或服务端 | 收到的报文不符合本规范。 |
130 | 0x82 | 协议错误 | 客户端或服务端 | 收到意外的或无序的报文。 |
131 | 0x83 | 实现指定错误 | 客户端或服务端 | 收到的报文有效,但根据实现无法进行处理。 |
135 | 0x87 | 未授权 | 服务端 | 请求没有被授权 |
137 | 0x89 | 服务端正忙 | 服务端 | 服务端正忙且不能继续处理此客户端的请求。 |
139 | 0x8B | 服务正关闭 | 服务端 | 服务正在关闭。 |
141 | 0x8D | 保持连接超时 | 服务端 | 连接因为在超过1.5倍的保持连接时间内没有收到任何报文而关闭。 |
142 | 0x8E | 会话被接管 | 服务端 | 另一个使用了相同的客户标识符的连接已建立,导致此连接关闭。 |
143 | 0x8F | 主题过滤器无效 | 服务端 | 主题过滤器格式正确,但不被服务端所接受。 |
144 | 0x90 | 主题名无效 | 客户端或服务端 | 主题名格式正确,但不被客户端或服务端所接受。 |
147 | 0x93 | 超出接收最大值 | 客户端或服务端 | 客户端或服务端收到了数量超过接收最大值的未发送PUBACK或PUBCOMP的发布消息。 |
148 | 0x94 | 主题别名无效 | 客户端或服务端 | 客户端或服务端收到的PUBLISH报文包含的主题别名大于其在CONNECT或CONNACK中发送的主题别名最大值。 |
149 | 0x95 | 报文过大 | 客户端或服务端 | 报文长度大于此客户端或服务端的最大报文长度。 |
150 | 0x96 | 消息速率过高 | 客户端或服务端 | 收到的数据速率太高。 |
151 | 0x97 | 超出配额 | 客户端或服务端 | 已超出实现限制或管理限制。 |
152 | 0x98 | 管理操作 | 客户端或服务端 | 连接因为管理操作被关闭。 |
153 | 0x99 | 载荷格式无效 | 客户端或服务端 | 载荷格式与指定的载荷格式指示符不匹配。 |
154 | 0x9A | 不支持保留 | 服务端 | 服务端不支持保留消息。 |
155 | 0x9B | 不支持的QoS等级 | 服务端 | 客户端指定的QoS等级大于CONNACK报文中指定的最大QoS等级。 |
156 | 0x9C | (临时)使用其他服务端 | 服务端 | 客户端应该临时使用其他服务端。 |
157 | 0x9D | 服务端已(永久)移动 | 服务端 | 服务端已移动且客户端应该永久使用其他服务端。 |
158 | 0x9E | 不支持共享订阅 | 服务端 | 服务端不支持共享订阅。 |
159 | 0x9F | 超出连接速率限制 | 服务端 | 此连接因为连接速率过高而被关闭。 |
160 | 0xA0 | 最大连接时间 | 服务端 | 超出为此连接授予的最大连接时间。 |
161 | 0xA1 | 不支持订阅标识符 | 服务端 | 服务端不支持订阅标识符;订阅未被接受。 |
162 | 0xA2 | 不支持通配符订阅 | 服务端 | 服务端不支持通配符订阅;订阅未被接受。 |
客户端或服务端发送DISCONNECT报文时必须使用一种DISCONNECT原因码 [MQTT-3.14.2-1]。如果原因码为0x00(正常断开)且没有属性,原因码和属性长度可以被省略。这种情况下DISCONNECT报文剩余长度为0。
非规范评注
DISCONNECT报文用于指示断开的原因,例如没有确认报文(比如QoS等级0的发布消息)或当客户端或服务端不能继续处理连接。
非规范评注
客户端可以使用这些信息来决定是否重新连接,以及在重新尝试之前应该等待多长时间。
DISCONNECT报文可变报头中的属性(Properties)的长度被编码为变长字节整数。如果剩余长度小于2,属性长度使用0。
17 (0x11) ,会话过期间隔(Session Expiry Interval)标识符。
跟随其后的是用四字节整数表示的以秒为单位的会话过期间隔(Session Expiry Interval)。包含多个会话过期间隔将造成协议错误(Protocol Error)。
如果没有设置会话过期间隔,则使用CONNECT报文中的会话过期间隔。
会话过期间隔不能由服务端的DISCONNECT报文发送 [MQTT-3.14.2-2]。
如果CONNECT报文中的会话过期间隔为0,则客户端在DISCONNECT报文中设置非0会话过期间隔将造成协议错误(Protocol Error)。如果服务端收到这种非0会话过期间隔,则不会将其视为有效的DISCONNECT报文。服务端使用包含原因码为0x82(协议错误)的DISCONNECT报文,如4.13节所述。
31 (0x1F) ,原因字符串(Reason String)标识符。
跟随其后的是UTF-8编码字符串表示断开原因。此原因字符串是为诊断而设计的可读字符串,不应该被接收端所解析。
如果此属性使得DISCONNECT报文的长度超出了接收端指定的最大报文长度,则发送端不能发送此属性 [MQTT-3.14.2-3]。包含多个原因字符串将造成协议错误(Protocol Error)。
38 (0x26) ,用户属性(User Property)标识符。
跟随其后的是UTF-8字符串对。此属性可用于向客户端提供包括诊断信息在内的附加信息。如果加上用户属性之后的DISCONNECT报文长度超出了接收端指定的最大报文长度,则发送端不能发送此属性 [MQTT-3.14.2-4]。用户属性允许出现多次,以表示多个名字/值对,且相同的名字可以多次出现。
28 (0x1C) ,服务端参考(Server Reference)标识符。
跟随其后的是一个UTF-8编码字符串,客户端可以使用它来识别其他要使用的服务端。包含多个服务端参考将造成协议错误(Protocol Error)。
服务端发送包含一个服务端参考和原因码0x9C((临时)使用其他服务端)或0x9D(服务端已(永久)移动)的DISCONNECT报文,如4.13节所述。
关于如何使用服务端参考,参考4.11节服务端重定向。
图 3-24 - DISCONNECT 报文可变报头非规范示例 DISCONNECT packet Variable Header non-normative example
说明 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
---|---|---|---|---|---|---|---|---|---|
断开原因码 | |||||||||
byte 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | |
属性 | |||||||||
byte 2 | 长度 (5) | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 |
byte 3 | 会话过期间隔标识符 (17) | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 |
byte 4 | 会话过期间隔标识符 (17) | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
byte 5 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | |
byte 6 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | |
byte 7 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
DISCONNECT报文没有有效载荷。
发送端发送完DISCONNECT报文之后:
- 不能再在此网络连接上发送任何MQTT控制报文 [MQTT-3.14.4-1]。
- 必须关闭网络连接 [MQTT-3.14.4-2]。
接收到包含原因码为0x00(成功)的DISCONNECT时,服务端:
- 必须丢弃任何与当前连接相关的遗嘱消息,而不发布它 [MQTT-3.14.4-3],如3.1.2.5节所述。
接收到DISCONNECT报文时,接收端:
- 应该关闭网络连接
- 3.0 Contents – MQTT控制报文
- 3.1 CONNECT – 连接服务端
- 3.2 CONNACK – 确认连接请求
- 3.3 PUBLISH – 发布消息
- 3.4 PUBACK –发布确认
- 3.5 PUBREC – 发布收到(QoS 2,第一步)
- 3.6 PUBREL – 发布释放(QoS 2,第二步)
- 3.7 PUBCOMP – 发布完成(QoS 2,第三步)
- 3.8 SUBSCRIBE - 订阅主题
- 3.9 SUBACK – 订阅确认
- 3.10 UNSUBSCRIBE –取消订阅
- 3.11 UNSUBACK – 取消订阅确认
- 3.12 PINGREQ – 心跳请求
- 3.13 PINGRESP – 心跳响应
- 3.14 DISCONNECT –断开连接
- 3.15 AUTH – 认证交换