1.1 TCP和UDP的心跳包是用来维持长连接的
心跳包只是用来检测socket的链接状态
2.1 非阻塞情况下TCP 心跳包是否有必要建立心跳包
需要,
a.如果说 严格 检测掉线的话 那么不管是不是非阻塞 都需要心跳包。(主要是因为心跳比较方便),如果想保持长连接,就需要定期发送心跳包
b.
1). A和Z通信。实际路线可能是: A->b->c->d->...->Z。
2). 后来,c和d有别扭,于是: A->b->c 「断X了」 d->->Z。
3). 除非有超时机机制,否则recv函数不会知道c和d的分手的事。
3.1 TCP自带心跳包定时为2小时,是全局TCP心跳超时,会影响系统其他应用网络连接
TCP有个KeepAlive开关,打开后可以用来检测死连接。通常默认是2小时,可以自己设置。但是注意,这是TCP的全局设置。假如为了能更及时的检测出断开的连接,把tcp_keepalive_time
和tcp_keepalive_intvl
的时间改小(参考:Link),该机器上所有应用程序的KeepAlive检测间隔都会变小,显然是不能接受的。因为不同应用程序的需求是不一样的。
4.1 recv 返回值判断连接情况,
a. 返回0
阻塞接收的recv有时候会返回0,这仅在socket被正常关闭时才会发生。
1) 正常关闭socket closesocket;
2)关机
b.返回-1
1) 阻塞,一般对于阻塞的socket都会用setsockopt来设置socket的超时。
当超时时间到达后,recv会返回错误,也就是-1,关闭重连接,无需心跳包
2) 掉线,断网直接关闭程序
假设使用Socket基于TCP通信协议进行C/S通信编程,客服端已经成功与服务端建立tcp连接,并且可以正常进行收发数据。
当一段时间后,服务端的程序如果调用closesocket(sClient);WSACleanup();函数关闭socket,
那么客户端的recv()将会返回0;
如果服务端没有调用closesocket(sClient);而只调用WSACleanup();或直接关闭程序,
那么客户端的recv()将会返回-1(SOCKET_ERROR)。
以上结果在局域网经过实际验证。
3)由于终端信号,服务端返回-,但是客户端依然连接,能发数据,怎么办? 心跳包重连接
其实,要判定掉线,只需要send或者recv一下,如果结果为零,则为掉线。但是,在长连接下,有可能很长一段时间都没有数据往来。理论上说,这个连接是一直保持连接的,但是实际情况中,如果中间节点出现什么故障是难以知道的。更要命的是,有的节点(防火墙)会自动把一定时间之内没有数据交互的连接给断掉。在这个时候,就需要我们的心跳包了,用于维持长连接,保活。
5.1 心跳包超时时间20~40s适宜
4.1 附录
https://www.zhihu.com/question/57736822
https://blog.csdn.net/qq_23167527/article/details/54290726
https://blog.csdn.net/liaomengge/article/details/50760831
https://www.zhihu.com/question/20849677/answer/16384522
https://www.cnblogs.com/nightwatcher/archive/2012/08/16/2643145.html
https://blog.csdn.net/tiandyoin/article/details/30044781
https://blog.csdn.net/baodi_z/article/details/43449315
http://www.nowamagic.net/academy/detail/23350382