面朝大海 春暖花开
分类: 网络与安全
2025-04-15 09:06:01
Clean Start 位于 CONNECT 报文的 可变报头,客户端在连接时通过这个字段指定是否复用已存在的会话,它只有 0 和 1 两个可取值。
当 Clean Start 被设置为 0,如果服务端存在与客户端连接时指定的 Client ID 关联的会话,那么它必须使用这个会话来恢复通信。
如果不存在任何与该 Client ID 关联的会话,则服务端必须创建一个全新的会话。这时,客户端使用的是旧的会话,服务端使用的是全新的会话,两边的会话状态出现了不一致。所以服务端必须将 CONNACK 报文中的 Session Present 字段设置为 0,以让客户端知晓它期望的会话不存在,如果客户端想要继续此网络连接,就必须丢弃它保存的会话状态。
当 Clean Start 设置为 1,客户端和服务端必须丢弃任何已存在的会话,并开始一个全新的会话。相应地,服务端也会把 CONNACK 报文中的 Session Present 字段设置为 0。
Session Expiry Interval 同样位于 CONNECT 报文的可变报头,不过它是一个可选的连接 属性。它被用来指定会话在网络断开后能够在服务端保留的{BANNED}最佳长时间,如果到达过期时间但网络连接仍未恢复,服务端就会丢弃对应的会话状态。它有三个典型的值:
每个 MQTT 客户端都可以独立设置自己的 Session Expiry Interval,我们可以根据实际需要来灵活地设置过期时间,比如一部分客户端不需要持久会话,一部分客户端只需要会话保留几分钟来避免网络波动带来的影响,而另一部分客户端则可能需要会话保留更长的时间。
MQTT 还允许客户端在断开连接时更新会话过期时间,这主要依靠 DISCONNECT 报文中 Session Expiry Interval 属性实现。比较常见的一个应用场景是,客户端在上线时将会话过期时间设置为一个大于 0 的值,避免网络中断影响正常业务。然后在客户端完成所有业务主动下线时,将会话过期时间更新为 0,这样服务端也可以及时地释放会话。
服务端使用 Client ID 来唯一地标识每个会话,如果客户端想要在连接时复用之前的会话,那么必须使用与此前一致的 Client ID。所以当我们使用服务端自动分配 Client ID 的功能时,客户端必须将 CONNACK 报文中返回的 Assigned Client Identifier 保存下来以供下次使用。
注意,MQTT 5.0 之前的协议版本并不支持服务端返回自动分配的 Client ID,所以在由服务端自动分配 Client ID 和使用持久会话之间,我们只能二选一。