服务端的会话状态
1. 客户端订阅的消息
2. 已发送,但还未完成确认的QoS 1和QoS 2消息
3. 等待发送的QoS 0,QoS 1,QoS 2消息
4. 从客户端收到的,还没有完成确认的QoS 2消息
5. 遗嘱消息和遗嘱延迟间隔
6. 会话是否存在
客户端的会话状态
1. 已发送但未完成确认
如何选择会话的生命周期
需要持久会话
1. 不希望错过离线期间的消息
2. 不希望QoS 1和QoS 2消息丢失
3. 不希望每次连接都需要重新建立订阅
4. 设备定期休眠,不希望长时间维护连接
不需要持久会话
1. 只对外发布QoS 0消息,不会接受任何消息
2. 只订阅QoS 0消息,不关心离线期间的消息
会话相关字段
Clean Start = 0
尝试从已存在的会话中恢复通信
Clean Start = 1
丢弃任何已存在的会话并创建新会话
Session Expiry Interval
执行会话在连接断开后能够保留的最长时间
Session Expiry Interval = 0
会话将在网络连接断开时结束
Session Expiry Interval > 0
会话将在连接断开的多少秒后过期
Session Expiry Interval = 0XFFFFFFFF
会话永不过期
会话练习
场景1:在会话过期前重新连接可以不用再次订阅
STEP 1: [订阅端]Clean Start=1,Session Expiry Interval= 300,创建一个全新的持久会话。
STEP 2: [订阅端]订阅主题 a
STEP 3: [订阅端]断开连接,将 Clean Start 设置为0,然后重连
STEP 4: [发布端]新建一个连接向主题a发布消息
现象:订阅端可以收到消息
与非持久会话对比:
STEP 1:[订阅端]Clean Start=1,Session Expiry lnterval= 0,使用全新的会话创建连接
STEP 2:[订阅端]订阅主题 a
STEP 3:[订阅端]断开连接,将 Clean Start 设置为 0,Session Expiry Interval保持不变然后重连
STEP 4:[发布端]接向主题a发布消息
现象:订阅端无法收到消息,必须重新订阅
场景2:离线期间,会话可以为客户端缓存新到达的 QoS (可选)、QoS1和QoS2消息
STEP 1:[订阅端] Clean Start= 1,Session Expiry lnterval= 300,创建一个全新的持久会话。
STEP2:[订阅端]订阅主题a,然后断开连接
STEP 3:[发布端]主题a发布消息 1,2,3
STEP 4:[订阅端]Clean Start 设置为 0,Session Expiry lnterval 保持不变,然后重连
现象:发现按顺序收到之前发布的消息
对比创建全新的会话:
STEP 4:[订阅端]Clean Start 设置为 1,Session Expiry lnterval 保持不变,然后重连现象:我们将不会收到之前发布的消息
与非持久会话对比:
STEP 1:[订阅端]Clean Start = 1,Session Expiry lnterval= 0,使用全新的会话创建连接
STEP2:[订阅端]订阅主题a,然后断开连接
STEP 3:[发布端]向主题a 发布消息 1,2,3
STEP4:[订阅端]Clean Start 设置为0(这是为了尝试复用会话,但代理中已经没有对应的会话了,所以会创建一个全新的会话),Session Expiry lnterval 保持不变然后重连
现象:我们将不会接收之前按发布的消息
场景3: 与MQTT3.1.1的区别
STEP 1: [订阅端] Clean Session =0,建立连接,订阅主题a,断开连接
STEP 2: [发布端]向主题a发布两条消息
STEP 3: [订阅端]保持 Clean Session = 0,重连,收到消息。
STEP 4: [订阅端]断开连接,发布端发布两条消息
STEP 5: [订阅端] Clean Session =1重连,代理将创建全新的会话,所以订阅端不会收到消息
STEP 6: [订阅端]断开连接
STEP 7: [发布端]发布两条消息。即便订阅端 Clean Session =0重连,仍然不会收到消息