From cf6fbb5f416280e4505138800260286f8fddee28 Mon Sep 17 00:00:00 2001 From: darkwolf Date: Tue, 17 Mar 2026 06:30:12 +0100 Subject: [PATCH] use min(interval, 30s) for TCP keepalive period Adapt keepalive to the configured interval: for short intervals (e.g. 10s) detection is faster, for long intervals (e.g. 10min) it caps at 30s as a safety net. Add comments explaining what problem keepalive solves and its detection time limitation. --- client/client.go | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/client/client.go b/client/client.go index 3fca5ff..74655c7 100644 --- a/client/client.go +++ b/client/client.go @@ -55,9 +55,21 @@ func NewClient(conn net.Conn, interval time.Duration, maxClients int64) *Client } atomic.AddInt64(&numCurrentClients, 1) // Enable TCP keepalive to detect dead peers at the kernel level. + // This is a safety net for long intervals where the write deadline + // alone would be too slow to detect dead connections. For example, + // with interval=10min, without keepalive a ghost connection would + // go undetected for 10+ minutes. + // Keepalive cannot detect peers that are alive at the TCP level + // (kernel still responds to probes) but stalled at the application + // level — the write deadline in Send() covers that case. + // Detection time: ~idle + 9 probes (e.g. 10s + 9×10s ≈ 100s on Linux). if tcpConn, ok := conn.(*net.TCPConn); ok { tcpConn.SetKeepAlive(true) - tcpConn.SetKeepAlivePeriod(30 * time.Second) + keepalive := interval + if keepalive > 30*time.Second { + keepalive = 30 * time.Second + } + tcpConn.SetKeepAlivePeriod(keepalive) } addr := conn.RemoteAddr().(*net.TCPAddr) glog.V(1).Infof("ACCEPT host=%v port=%v n=%v/%v\n", addr.IP, addr.Port, numCurrentClients, maxClients)