TCP keepalive长连接心跳保活

Posted brant

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了TCP keepalive长连接心跳保活相关的知识,希望对你有一定的参考价值。


比如:客户端与服务端进行握手时,经常无法握手成功,收不到回复; 需要建立保活机制。

 

1. 服务端Linux服务器新增系统内核参数配置。

在/etc/sysctl.conf文件中再添加如:

#允许的持续空闲时长,在TCP保活打开的情况下,最后一次数据交换到TCP发送第一个保活探测包的间隔,即允许的持续空闲时长,或者说每次正常发送心跳的周期,默认值为7200s(2h)。
net.ipv4.tcp_keepalive_time=1800
#在tcp_keepalive_time之后,没有接收到对方确认,继续发送保活探测包的发送频率,
net.ipv4.tcp_keepalive_intvl=30
#在tcp_keepalive_time之后,没有接收到对方确认,继续发送保活探测包次数
net.ipv4.tcp_keepalive_probes=3

执行sysctl -p来使它生效:
检测一下是否已经生效:sysctl -a | grep keepalive

2. Java/netty服务器中配置使用

ServerBootstrap bootstrapHttp =new ServerBootstrap(new NioserverSocketChannelFactory(Executors.newCachedThreadPool(), Executors.newCachedThreadPool()));
bootstrapHttp.setPipelineFactory(new HttpServerPipelineFactory());
bootstrapHttp.setOption("child.tcpNoDelay", true);
bootstrapHttp.setOption("child.keepAlive", true);
bootstrapHttp.bind(new InetSocketAddress(ip, http_port));

3.关闭tcp_timestamps选项

客户在服务端开启了某个端口,但是在客户端telnet确一直不通。通过在服务端抓包发现,客户端的syn分节已经到达,但是服务端并没有应答。
net.ipv4.tcp_tw_recycle选项可能引起这个问题,于是关闭了这个选项,问题果然得以解决。这里分析一下原因。
有些服务器(当然客户端也可以)为了避免TIME_WAIT状态占用连接,希望能加快TIME_WAIT状态的回收,通常将net.ipv4.tcp_tw_recycle选项开启。
当然这个选项的生效要依赖net.ipv4.tcp_timestamps选项的开启。虽然开启这个选项能够加快TIME_WAIT连接的回收,但却引入了另一个问题。我们先看下tcp_tw_recycle选项的工作机制:
当开启了tcp_tw_recycle选项后,当连接进入TIME_WAIT状态后,会记录对应远端主机最后到达分节的时间戳。如果同样的主机有新的分节到达,且时间戳小于之前记录的时间戳,即视为无效,相应的数据包会被丢弃(rfc1323)。
Linux是否启用这种行为取决于tcp_timestamps和tcp_tw_recycle,因为tcp_timestamps缺省就是开启的,所以当tcp_tw_recycle被开启后,实际上这种行为就被激活了

在/etc/sysctl.conf文件中再添加如:
#不检查请求的时间戳

net.ipv4.tcp_timestamps=0

 










以上是关于TCP keepalive长连接心跳保活的主要内容,如果未能解决你的问题,请参考以下文章

iOS 即时通讯(二):心跳保活

不为人知的网络编程:彻底搞懂TCP协议层的KeepAlive保活机制

012_TCP keepalive 和 http keep-alive

基于TCP的移动端IM即时通讯开发仍然需要心跳保活

Python实现心跳保活TCP长连接

Python实现心跳保活TCP长连接