TCP server保活(keepalive)的应用

来源:互联网 发布:mysql alter修改表数据 编辑:程序博客网 时间:2024/06/08 12:13

问题来源:

近期开发一个同时存在长连接和短连接的TCP server。

在存在长连接的client时,server接收采用的是非阻塞的模式。如何确保在客户端异常结束进程之后,可判断客户端已死,断掉连接,结束线程。

解决方案:

1>、使用应用层面的心跳包

2>、使用协议层面的TCP 保活机制, keepalive。


具体实现:

心跳包不做过多解释,具体记录一下keepalive的实现。

协议解读(RFC1122#TCP Keep-Alives):

  1. TCP Keepalive虽不是标准规范,但操作系统一旦实现,默认情况下须为关闭,可以被上层应用开启和关闭。
  2. TCP Keepalive必须在没有任何数据(包括ACK包)接收之后的周期内才会被发送,允许配置,默认值不能够小于2个小时
  3. 不包含数据的ACK段在被TCP发送时没有可靠性保证,意即一旦发送,不确保一定发送成功。系统实现不能对任何特定探针包作死连接对待
  4. 规范建议keepalive保活包不应该包含数据,但也可以包含1个无意义的字节,比如0x0。
  5. SEG.SEQ = SND.NXT-1,即TCP保活探测报文序列号将前一个TCP报文序列号减1。SND.NXT = RCV.NXT,即下一次发送正常报文序号等于ACK序列号。


在linux中的实现:

可在系统中设置(这里使用的是ubuntu):

echo 1>  /proc/sys/net/ipv4/tcp_keepalive_time
echo 10 > /proc/sys/net/ipv4/tcp_keepalive_intvl 
echo 10 > /proc/sys/net/ipv4/tcp_keepalive_probes


设置应用部分:


客户端在windows平台下:
1,用户进程被杀死,tcp协议栈将异常断开连接,另一方可以获得通知,如errno 104(Connection reset by peer
2,用户进程退出且未调用closesocket,另一方可以获得通知errno 104
3,系统关机(正常的),另一方可以获得通知errno 104
4,系统关机(异常的),另一方不一定可以获得通知
5,系统断电,另一方无法获得通知
6,网络突然故障(例如网线被拔掉),另一方无法获得通知

由此可见,断电和断网时,对方无法获得通知,recv将一直阻塞直到永远。keepalive主要就是为了应对这种情况,若干保活包不能送达,对方即认为连接丢失。
这时errno读取为110(Connection timed out

0 0
原创粉丝点击