研究MQTT通过Keep Alive来确认连接是否正常

MQTT是tcp连接,tcp连接的IsConnected记录的是上次网络IO的状态,很多时候连接都断了IsConnected依然是true

MQTT有个Keep Alive参数,可以理解为保活周期,这个参数官方的说法是客户端发送两次 MQTT 协议包之间的最大间隔时间

按照我的理解就是如果客户端和服务端长时间没有数据通讯(发送和接收),达到Keep Alive时间后,约定客户端就可以向服务端发送 PINGREQ 协议包用来判定连接是否正常,如果连接正常,则一切安好,如果连接不正常,客户端应当断开连接,这里的【约定,应当】估计是需要客户端开发完善的,我现在用的M2Mqtt类库貌似就实现了这个效果

Keep Alive参数在服务器也有效果,服务端在1.5个Keep Alive内,既没有收到客户端发布订阅报文,也没有收到PINGREQ心跳报文时,主动心跳超时会断开客户端TCP连接。

对于 Keep Alive 机制,我们还需要记住以下几点:

  • 如果在一个 Keep Alive 时间间隔内,Client 和 Broker 有过数据包传输,比如 PUBLISH,Client 就没有必要再使用 PINGREQ 了,在网络资源比较紧张的情况下这点很重要;
  • Keep Alive 值是由 Client 指定的,不同的 Client 可以指定不同的值;
  • Keep Alive 的最大值为 18 小时 12 分 15 秒;
  • Keep Alive 值如果设为 0 的话,代表不使用 Keep Alive 机制。

借鉴https://blog.csdn.net/qq997758497/article/details/90677479

由于超过Keep Alive时间后会发送PINGREQ协议包,网络IO更新了状态,此时的IsConnected就变得可信了,而且大部分类库应该都会有个连接断开事件,这样无论是自己定时轮询IsConnected,还是通过监控连接断开事件,都能准确得知道当前连接是否正常,发现连接断开后,就可以尝试连重连了

如果使用定时器轮询重连,需要考虑如果重连发生阻塞,定时器会不停申请重连操作,可能会搞崩系统,因此推荐在断开事件中处理重连(但是如果重连失败,可能触发不了新的断开事件,也就是说只能重连一次),如果只能轮询,那就需要想办法保证重连时不再申请新的重连,比如用延迟定时器,或者用锁+标志位控制

 

posted @ 2023-02-23 11:03  WmW  阅读(563)  评论(0编辑  收藏  举报