TCP keepalive长连接心跳保活

本文介绍了如何在Linux服务器上配置TCP保活机制,包括系统内核参数调整、Java/Netty应用配置及关闭tcp_timestamps选项等内容。


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

 

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

 

转载于:https://www.cnblogs.com/brant/p/9377098.html

### TCP 心跳包实现保活机制原理与示例 #### 一、TCP 心跳包的保活机制原理 TCP协议本身提供了一种称为 `keepalive` 的功能来检测连接的有效性。当启用该功能后,操作系统会在一段时间内未收到数据的情况下自动发送探测包到对端设备以确认其状态[^1]。 在Linux环境下,通过设置socket选项可以激活这种行为。具体来说,有三个主要参数用于控制此过程的行为: - **TCP_KEEPIDLE**: 设置首次探针发出前等待的时间长度(单位为秒)。默认值通常为7200秒 (即两小时)[^4]。 - **TCP_KEEPCNT**: 定义连续失败的最大重试次数之后才判定连接断开,默认可能为9次尝试。 - **TCP_KEEPINTVL**: 设定两次连续探针之间相隔多久再发下一次试探消息,默认间隔大约为75秒。 这些配置项允许开发者依据实际需求调整超时策略从而优化网络性能表现以及资源消耗情况。 #### 二、代码实例展示如何开启Socket KeepAlive 功能 以下是基于C语言的一个简单例子演示怎样初始化一个支持Keep Alive特性的套接字: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/tcp.h> int main() { int sockfd; /* 创建一个新的流式套接口 */ if ((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0){ perror("Failed to create socket"); exit(EXIT_FAILURE); } // 启动KEEPALIVE特性 int optval = 1; setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval)); // 配置具体的KEEPALIVE参数 int idle_time = 60; // 开始之前闲置多少秒 int interval = 10; // 探测报文之间的间隔时间(秒) int max_probes = 3; // 失败后的最大探测数 setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE, &idle_time, sizeof(idle_time)); setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL,&interval,sizeof(interval)); setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPCNT ,&max_probes ,sizeof(max_probes )); printf("Socket configured with KEEP ALIVE options.\n"); close(sockfd); return 0; } ``` 这段程序展示了如何利用标准库函数调用来定制化我们的SOCKET对象使其具备更强大的健壮性和错误恢复能力。 另外,在某些应用场合除了依赖底层传输层提供的服务外还需要额外增加上层的应用级心跳信号交换流程以便进一步增强可靠性保障措施。比如WebSocket通信场景下的双重心跳方案就是典型代表之一[^2]: ```java // 发送协议层面PING帧作为低层次健康状况监测手段 session.getBasicRemote().sendPing(null); // 对于特定类型的消息给予回应构成高层次业务交互验证环节 if ("HEARTBEAT".equals(message)) { sendMessage("HEARTBEAT_ACK"); } ``` 这里分别实现了两个不同维度上的存活检验方式共同作用确保整个链路处于正常工作状态下运行良好。 值得注意的是虽然上述案例采用JAVA表述形式但实际上背后蕴含的设计理念具有广泛的适用范围并不局限于某一种特殊语法结构之中[^3]。 #### 结论 综上所述,无论是借助系统内置的能力还是自行构建专属解决方案都能够有效地达成维持持久型链接的目的同时兼顾效率考量因素达到最佳平衡点。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值