# 3.10 UNSUBSCRIBE –取消订阅

客户端发送UNSUBSCRIBE报文给服务端，用于取消订阅主题。

## 3.10.1 固定报头

#### 图例 3.28 – UNSUBSCRIBE报文固定报头

| **Bit** | **7**           | **6** | **5** | **4** | **3** | **2** | **1** | **0** |
| ------- | --------------- | ----- | ----- | ----- | ----- | ----- | ----- | ----- |
| byte 1  | MQTT控制报文类型 (10) | 保留位   |       |       |       |       |       |       |
|         | 1               | 0     | 1     | 0     | 0     | 0     | 1     | 0     |
| byte 2  | 剩余长度            |       |       |       |       |       |       |       |

UNSUBSCRIBE报文固定报头的第3,2,1,0位是保留位且**必须**分别设置为0,0,1,0。服务端**必须**认为任何其它的值都是不合法的并关闭网络连接 \[MQTT-3.10.1-1]。

**剩余长度字段**

等于可变报头的长度加上有效载荷的长度。

## 3.10.2 可变报头

可变报头包含一个报文标识符。2.3.1节提供了有关报文标识符的更多信息。

#### 图例 3.29 – UNSUBSCRIBE报文可变报头

| **Bit** | **7**     | **6** | **5** | **4** | **3** | **2** | **1** | **0** |
| ------- | --------- | ----- | ----- | ----- | ----- | ----- | ----- | ----- |
| byte 1  | 报文标识符 MSB |       |       |       |       |       |       |       |
| byte 2  | 报文标识符 LSB |       |       |       |       |       |       |       |

## 3.10.3 有效载荷

UNSUBSCRIBE报文的有效载荷包含客户端想要取消订阅的主题过滤器列表。UNSUBSCRIBE报文中的主题过滤器**必须**是连续打包的、按照1.5.3节定义的UTF-8编码字符串 \[MQTT-3.10.3-1]。

UNSUBSCRIBE报文的有效载荷**必须**至少包含一个消息过滤器。没有有效载荷的UNSUBSCRIBE报文是违反协议的 \[MQTT-3.10.3-2]。有关错误处理的更多信息请查看4.8节。

### 有效载荷非规范示例

> [图例 3.30 -有效载荷字节格式非规范示例](#_Figure_3.30_-) 展示了 [表格 3.7 -有效载荷非规范示例](#_Table3.6_-_Payload) 简要描述的UNSUBSCRIBE报文的有效载荷。

#### 表格 3.7 -有效载荷非规范示例

| 主题过滤器 | “a/b” |
| ----- | ----- |
| 主题过滤器 | “c/d” |

#### 图例 3.30 -有效载荷字节格式非规范示例

|         | **描述**         | **7** | **6** | **5** | **4** | **3** | **2** | **1** | **0** |
| ------- | -------------- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | ----- |
| 主题过滤器   |                |       |       |       |       |       |       |       |       |
| byte 1  | Length MSB (0) | 0     | 0     | 0     | 0     | 0     | 0     | 0     | 0     |
| byte 2  | Length LSB (3) | 0     | 0     | 0     | 0     | 0     | 0     | 1     | 1     |
| byte 3  | ‘a’ (0x61)     | 0     | 1     | 1     | 0     | 0     | 0     | 0     | 1     |
| byte 4  | ‘/’ (0x2F)     | 0     | 0     | 1     | 0     | 1     | 1     | 1     | 1     |
| byte 5  | ‘b’ (0x62)     | 0     | 1     | 1     | 0     | 0     | 0     | 1     | 0     |
| 主题过滤器   |                |       |       |       |       |       |       |       |       |
| byte 6  | Length MSB (0) | 0     | 0     | 0     | 0     | 0     | 0     | 0     | 0     |
| byte 7  | Length LSB (3) | 0     | 0     | 0     | 0     | 0     | 0     | 1     | 1     |
| byte 8  | ‘c’ (0x63)     | 0     | 1     | 1     | 0     | 0     | 0     | 1     | 1     |
| byte 9  | ‘/’ (0x2F)     | 0     | 0     | 1     | 0     | 1     | 1     | 1     | 1     |
| byte 10 | ‘d’ (0x64)     | 0     | 1     | 1     | 0     | 0     | 1     | 0     | 0     |

## 3.10.4 响应

UNSUBSCRIBE报文提供的主题过滤器（无论是否包含通配符）**必须**与服务端持有的这个客户端的当前主题过滤器集合逐个字符比较。如果有任何过滤器完全匹配，那么它（服务端）自己的订阅将被删除，否则不会有进一步的处理 \[MQTT-3.10.4-1]。

如果服务端删除了一个订阅：

* 它**必须**停止分发任何新消息给这个客户端 \[MQTT-3.10.4-2]。
* 它**必须**完成分发任何已经开始往客户端发送的QoS 1和QoS 2的消息 \[MQTT-3.10.4-3]。
* 它**可以**继续发送任何现存的准备分发给客户端的缓存消息。

服务端**必须**发送UNSUBACK报文响应客户端的UNSUBSCRIBE请求。UNSUBACK报文**必须**包含和UNSUBSCRIBE报文相同的报文标识符 \[MQTT-3.10.4-4]。即使没有删除任何主题订阅，服务端也**必须**发送一个UNSUBACK响应 \[MQTT-3.10.4-5]。

如果服务端收到包含多个主题过滤器的UNSUBSCRIBE报文，它**必须**如同收到了一系列的多个UNSUBSCRIBE报文一样处理那个报文，除了将它们的响应合并到一个单独的UNSUBACK报文外。 \[MQTT-3.10.4-6]。

## 第三章目录 MQTT控制报文

* [3.0 Contents – MQTT控制报文]()
* [3.1 CONNECT – 连接服务端](0301-connect)
* [3.2 CONNACK – 确认连接请求](0302-connack)
* [3.3 PUBLISH – 发布消息](0303-publish)
* [3.4 PUBACK –发布确认](0304-puback)
* [3.5 PUBREC – 发布收到（QoS 2，第一步）](0305-pubrec)
* [3.6 PUBREL – 发布释放（QoS 2，第二步）](0306-pubrel)
* [3.7 PUBCOMP – 发布完成（QoS 2，第三步）](0307-pubcomp)
* [3.8 SUBSCRIBE - 订阅主题](0308-subscribe)
* [3.9 SUBACK – 订阅确认](0309-suback)
* [3.10 UNSUBSCRIBE –取消订阅](0310-unsubscribe)
* [3.11 UNSUBACK – 取消订阅确认](0311-unsuback)
* [3.12 PINGREQ – 心跳请求](0312-pingreq)
* [3.13 PINGRESP – 心跳响应](0313-pingresp)
* [3.14 DISCONNECT –断开连接](0314-disconnect)

## 项目主页

* [MQTT协议中文版](https://github.com/mcxiaoke/mqtt)
