本文共 2243 字,大约阅读时间需要 7 分钟。
此问题在面试中经常出现
给一个TCP套接字设置保持存活选项。如果keepalivetime小时内在该套接字的任意方向都没有数据的交换,则TCP就自动给对端发送一个保持存活探测分节(keep-alive probe)。这是一个对端必须响应的TCP分节,导致三种情况
此选项的功用是检测对端主机是否崩溃或变得不可达。如果对端进程崩溃,它的tcp将跨连接发送一个FIN,这可以通过select很容易检测到
使用方法:(类UNIX中)
在代码里针对每个socket进行单独设定, 使用起来灵活.
除了keepAlive 开关, 还有keepIdle, keepInterval, keepCount 3个属性, 使用简单, 如下:
int keepAlive = 1; // 开启keepalive属性. 缺省值: 0(关闭) int keepIdle = 60; // 如果在60秒内没有任何数据交互,则进行探测. 缺省值:7200(s) int keepInterval = 5; // 探测时发探测包的时间间隔为5秒. 缺省值:75(s) int keepCount = 2; // 探测重试的次数. 全部超时则认定连接失效..缺省值:9(次) setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (void*)&keepAlive, sizeof(keepAlive)); setsockopt(s, SOL_TCP, TCP_KEEPIDLE, (void*)&keepIdle, sizeof(keepIdle)); setsockopt(s, SOL_TCP, TCP_KEEPINTVL, (void*)&keepInterval, sizeof(keepInterval)); setsockopt(s, SOL_TCP, TCP_KEEPCNT, (void*)&keepCount, sizeof(keepCount));使用时需要 #include <netinet/tcp.h>, 否则 SOL_TCP 和 TCP_KEEPIDLE 等 3 个宏找不到 .
修改配置文件, 对整个系统所有的socket有效.我们可以用cat命令查看到系统中这几个默认的值.#cat /proc/sys/net/ipv4/tcp_keepalive_time 7200 #cat /proc/sys/net/ipv4/tcp_keepalive_intvl 75 #cat /proc/sys/net/ipv4/tcp_keepalive_probes 9修改它们:#echo 60 > /proc/sys/net/ipv4/tcp_keepalive_time #echo 5 > /proc/sys/net/ipv4/tcp_keepalive_intvl #echo 3 > /proc/sys/net/ipv4/tcp_keepalive_probes
自定义心跳消息结构,具体是服务器端还是客户端发送心跳包,看具体情况,另一端接收心跳信息后也要回应,逻辑上来说和设置SO_KEEPALIVE后tcp自带的探测过程相似。
tcp协议自带心跳的优势和劣势:
优势:
- tcp心跳提供最纯粹的检活功能(这可看着优势也可看成劣势),简洁有效
- 我们只需设置SO_KEPALIVE选项并设置相关参数,就可开启tcp协议的心跳机制,使得应用层开发的代码量减少。
- 更省流量
劣势:
- tcp只提供纯粹的检活功能,不灵活。
- 心跳除了说明应用程序还活着(进程还在,网络通畅),更重要的是表明应用程序还能正常工作。而 TCP keepalive 有操作系统负责探查,即便进程死锁,或阻塞,操作系统也会如常收发 TCP keepalive 消息。对方无法得知这一异常,而如果我们通过在应用层编写自己的心跳机制,可以处理这种问题
应用层实现的心跳机制优势额劣势:
优势:
- 灵活性更大,应用层可更加随意的控制探测包的内部结构(可以捎带额外的信息), 时间间隔、探测结果的分类处理等
- 更加通用,假如项目需要修改传输层协议或者移植平台,我们修改的代码量较少
劣势:
- 更费流量(因为处于应用层范畴)
- 增加了编写代码的工作量,增加了代码结构的复杂度
转载地址:http://dnumi.baihongyu.com/