模块建立的Socket一段时间后接收不到数据了是怎么回事?



  • 大家在使用WiFi模块通信的时候经常会遇到一个令人费解的问题:建立好Socket通信之后,原本通信还正常,可是过了一段时间后客户端(Client)发送消息,服务器端(Server)这边就接收不到信息。到底是我的Socket连接不好的原因,还是别的什么原因导致的正常的Socket断开?

    其实原因是这样的:一般Socket在建立之后会因为网络不稳定如断网,网络信号太差;或是路由器、网卡、交换机等设备原因出错而断开。更要命的是,有的节点(防火墙)会自动把一定时间之内没有数据交互的连接给断掉。这些Socket异常断线我们是避免不了的,但是我们可以通过一定的机制来检测Socket是否连接正常.

    什么机制呢?那就是心跳包机制,所谓的心跳包机制就是客户端(Client)或服务器端(Server)定时发送一个简单的信息包给对方告诉对方我还活着而已。心跳包之所以叫心跳包是因为:它像心跳一样每隔固定时间发一次,以此来告诉服务器,这个客户端还活着。事实上这是为了保持长连接,至于这个包的内容,是没有什么特别规定的,不过一般都是很小的包,或者只包含包头的一个空包。心跳包代码的作用就是让一端(一般是客服端)每隔一定的时间发送一个固定信息包给服务器端,服务器端收到后再回复一个固定信息给客户端,如果服务器端在规定的时间内没有收到客户端发送的信息包则视为客户端断开。

    所以如果发现自己建立的Socket一段时间后接收不了数据了,先要想一想自己是否有心跳包机制。一般的应用下,判定时间在30-40s比较不错。如果实在要求高,那就在6-9s

    心跳包机制实现的两种方法:

    • 1.应用层自己实现的心跳包
      由应用程序自己发送心跳包来检测连接是否正常,大致的方法是:服务器在一个 Timer事件中定时向客户端发送一个短小精悍的数据包,然后启动一个低级别的线程,在该线程中不断检测客户端的回应,如果在一定时间内没有收到客户端的回应,即认为客户端已经掉线;同样,如果客户端在一定时间内没有收到服务器的心跳包,则认为连接不可用。

    • 2.TCP的Keep-Alive保活机制
      因为要考虑到一个服务器通常会连接多个客户端,因此由用户在应用层自己实现心跳包,代码较多且稍显复杂,而利用TCP/IP协议层为内置的Keep-Alive功能来实现心跳功能则简单得多。不论是服务器端还是客户端,一方开启Keep-Alive功能后,就会自动在规定时间内向对方发送心跳包,而另一方在收到心跳包后就会自动回复,以告诉对方我仍然在线。因为开启Keep-Alive功能需要消耗额外的宽带和流量,所以TCP协议层默认并不开启Keep-Alive功能,尽管这微不足道,但在按流量计费的环境下增加了费用,另一方面,Keep-Alive设置不合理时可能会因为短暂的网络波动而断开正常的TCP连接。并且,默认的Keep-Alive超时需要7200000 ms,即2小时,探测次数为5次。对于很多服务端应用程序来说,2小时的空闲时间太长。因此,我们需要手工开启Keep-Alive功能并设置合理的Keep-Alive参数。


登录后回复
 

与 RAK支持中心 的连接断开,我们正在尝试重连,请耐心等待