linux socket心跳包发送间隔由tcp层keepalive参数控制,核心是tcp_keepidle(空闲启动时间)、tcp_keepintvl(探测间隔)、tcp_keepcnt(失败次数)三者协同;默认2小时+75秒+9次不适用业务,需显式调优,如idle=15、intvl=3、cnt=3时总超时约24秒,且应用层任何数据交互都会重置计时器。

Linux socket 中设置心跳包发送间隔,核心是控制 TCP 层的保活探测行为,不是应用层手动发包。关键在于正确配置 SO_KEEPALIVE 及其三个关联参数:空闲时间(TCP_KEEPIDLE)、探测间隔(TCP_KEEPINTVL)和失败次数(TCP_KEEPCNT)。默认值(2小时空闲、75秒间隔、9次重试)完全不适用于业务场景,必须显式调整。
明确心跳触发逻辑:先空闲,再探测
心跳不是“每隔N秒发一次”,而是:连接建立后,若连续 空闲 指定秒数(TCP_KEEPIDLE)未收发任何数据,才启动第一次探测;之后每间隔 TCP_KEEPINTVL 秒发一次探测包,最多尝试 TCP_KEEPCNT 次。只有全部失败,内核才通知应用层连接已断。
- 例如设
idle=20、intvl=5、cnt=3:连接静默满20秒后,开始发探测;第1次失败后等5秒发第2次,再等5秒发第3次;若3次全无响应,内核才标记连接失效 - 只要期间有任意应用层数据收发(哪怕一个字节),计时器就重置,重新等待20秒空闲
- 因此,心跳间隔实际是“探测间隔”,不是“发送间隔”;真正影响体验的是从空闲到断连的总耗时(20 + 5×3 = 35秒)
代码中逐 socket 设置(推荐)
在创建 socket 后、connect 或 bind 之前(或之后立即),调用 setsockopt 设置。需包含 <netinet></netinet> 才能使用 TCP 相关宏。
在无 root/sudo 权限的环境(云容器、VPS、隔离主机)中安装并配置 OpenClaw 浏览器工具的 headless Chrome。适用场景:...
- 启用保活:
setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) - 设空闲时间(秒):
setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &idle, sizeof(idle)) - 设探测间隔(秒):
setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &intvl, sizeof(intvl)) - 设探测次数:
setsockopt(fd, SOL_TCP, TCP_KEEPCNT, &cnt, sizeof(cnt)) - 常见组合:要求快速感知断连,可选
idle=15、intvl=3、cnt=3(总超时约24秒);对稳定性要求高但容忍稍慢,可用idle=30、intvl=5、cnt=4(总超时50秒)
避免常见陷阱
参数设置看似简单,但几个细节极易出错:
- 必须先启用 SO_KEEPALIVE,否则其他三个参数无效;且开启后不可动态关闭(需重建 socket)
- 参数单位全是秒(Linux 3.1+),不是毫秒;旧内核可能支持毫秒,但应统一按秒处理
- 应用层有定时数据交互时,TCP keepalive 可能永不触发——比如业务本身每10秒发一次消息,那 idle=20 就永远不启动探测;此时需评估是否还需 keepalive,或改用应用层心跳
- 服务端收到探测包会自动回复 ACK,无需应用层干预;但若中间防火墙丢弃 ACK,会导致误判断连
系统级配置(慎用)
修改 /proc/sys/net/ipv4/tcp_keepalive_* 会影响**所有**新创建的 socket,适合统一策略的嵌入式或网关设备,但不推荐在通用服务器上使用:
- 临时生效:
echo 15 > /proc/sys/net/ipv4/tcp_keepalive_time(对应 idle) -
echo 3 > /proc/sys/net/ipv4/tcp_keepalive_intvl(对应 intvl) -
echo 3 > /proc/sys/net/ipv4/tcp_keepalive_probes(对应 cnt) - 永久生效:写入
/etc/sysctl.conf,如net.ipv4.tcp_keepalive_time = 15 - 注意:已存在的 socket 不受此影响,只对后续新建连接生效










