有一个问题不知道大家注意过没有——为什么socket客户端在非正常断开后,服务器在很长一段时间内不会显示客户端断开?没有的话,大可以试试-。-
原因:
如果是正常终止客户端进程,系统会对进程正在占用的资源进行回收。此时客户端所占用的socket端口会被释放,服务器端也会被告知对方断开socket连接了,因此终止与该客户端的连接。而如果客户端非正常断开(比如客户端主机突然断电),则客户端的操作系统会在第一时间产生中断,保护操作系统。哪个操作系统还会特意耗费时间去回收socket资源←_←。所以即便客户端明明已经断开了连接,但服务器却迟迟没办法知道客户端断开的消息。因此会在较长一段时间内不会告诉编程者“某客户端已断开”,即便你写了在客户端断开后立刻回收资源的代码。
解决:
相信不少人都听说过“心跳包”吧。保持客户端与服务器长连接的话,心跳包是必不可少的。设定阈值n,心跳间隔时间T,当服务器在n*T的时间内没有听到客户端的心跳,那么就可以判定客户端“死亡”了,主动与它断开连接,回收资源。至于n和T怎么设置,纯看项目的需求和编程者的心情了。当然,心跳包的写法很多种,可以是服务器向客户端发心跳要求回应,也可以是客户端直接向服务器发心跳。不同的应用场景可能都不同。
血的经历:
当网络延迟高于n*T的时候,唉……(曾经设置n=2,T=8s,然而网络延迟——20000ms……别问我这种奇迹怎么发生,你在局域网边上开上百个路由器就知道了)