在进行socket相关编程的过程中我发现,Scoket不是那么稳定可靠,表现在以下方面:
-
如果长时间没有数据往来,连接会断掉(可能是路由或防火墙)
-
如果客户端断网, 服务端不能检测到。这会导致服务端一直占用资源,且发出的数据
没有发送成功
却不会出错
针对以上两个问题,一些解决方案如下。
-
设置socket的keepalive属性 。 但是在实践过程中发现并没有用,长时间没有数据传送仍然会关闭。
-
使用socket的sendUrgentData发送检测数据。但是可能会使数据流出现混乱。(不同系统、设备处理机制不一样,例如在我手机上数据流不会混乱,但是在虚拟机上就混乱了)
基于以上两个办法的思路,现在研究了以下办法:
-
对于第一个问题,在应用层实现
心跳机制
客户端开一个线程每隔一定时间发送一个心跳包,服务端设置recv的超时时间比心跳包时间间隔稍长(2倍为好)。超时接收不到数据包,说明客户端出现问题了,视为已经断开连接。 -
对于第二个问题, 可以在正式数据发送前发送
检测包
, 客户端收到检测包后立即返回一个响应。服务端收到响应,认为客户端还活着,即把正式数据发送。 -
对于第二个问题, 可以在收到数据后,返回一个
标识
。 例如客户端把数据发送后,如果在一定时间内得不到标识,则认为这条数据发送失败。