什么时候TCP连接被认为是空闲的?

Jen*_*ens 12 sockets linux tcp keep-alive retransmit-timeout

我需要在任何连接上启用TCP keepalive,现在我正在努力处理测试用例的结果.我想这是因为我真的不明白第一次发送keepalive探测器的时间.我tcp_keepalive_time在Linux 的文档中阅读了以下内容:

发送的最后一个数据包(简单的ACK不被认为是数据)和第一个keepalive探针之间的间隔; 在连接被标记为需要保持连接后,此计数器不再使用

其他一些消息来源表示这是连接空闲的时间,但它们没有进一步定义这意味着什么.我还调查了史蒂文斯找到一个更正式的定义,因为我想知道"最后发送的数据包"在考虑重传时实际意味着什么.

在我的测试用例中,我有一个连接,其中数据仅以相当高的速率从服务器发送到客户端.为了测试keepalive,我们拔掉了客户端网卡上的电缆.我现在可以看到网络堆栈尝试发送数据并进入重传状态,但是没有发送保持活动探测.在重传期间不发送保持活动探测是否正确?

cni*_*tar 17

我有一个连接,数据只以相当高的速率从服务器发送到客户端.

然后你永远不会看到Keepalive.当电线"静音"时发送Keepalive.RFC1122有一些解释re keepalive.

即使没有数据要发送,当连接空闲时,"保持活动"机制会定期探测连接的另一端.

回到你的问题:

其他一些消息来源表示这是连接空闲的时间,但它们没有进一步定义这意味着什么.

这是TCP在等待"hoy!还活着吗?"之前等待的时间.

$ cat /proc/sys/net/ipv4/tcp_keepalive_time
7200
Run Code Online (Sandbox Code Playgroud)

换句话说,你一直在使用TCP连接,它很棒.但是,在过去的2个小时里,没有任何东西要发送.假设连接仍然存在是否合理?假设中间的所有中间盒仍然具有关于您的连接的状态,这是否合理?意见各不相同,Keepalive不属于RFC793.

TCP规范不包括它可能的保持活动机制:(1)在瞬时Internet故障期间导致完美的连接断开; (2)消耗不必要的带宽("如果没有人使用连接,谁在乎它是否仍然好?")


为了测试keepalive,我们拔掉了客户端网卡上的电缆.

这不是测试keepalive.这是测试您的TCP重新传输策略,即TCP尝试传递消息的次数和频率.在Linux机器上,这(可能)最终测试net.ipv4.tcp_retries2:

如何在杀死活动TCP连接之前重试.RFC 1122表示限制应该超过100秒.这个数字太小了.默认值15对应于13-30分钟,具体取决于RTO.

RFC5482 - TCP用户超时选项提供了更多影响它的方法.

TCP用户超时控制在强制关闭连接之前传输的数据可能保持未确认的时间.

回到问题:

在重传期间不发送保持活动探测是否正确

这是有道理的:TCP已经试图从另一个对等方引出响应,空的keepalive将是多余的.


特定于Linux的(2.4+)选项可影响keepalive

  • TCP_KEEPCNT 丢弃连接之前TCP应发送的最大keepalive探测数.

  • TCP_KEEPIDLE如果SO_KEEPALIVE在此套接字上设置了套接字选项,则在TCP开始发送keepalive探测之前连接需要保持空闲的时间(以秒为单位)

  • TCP_KEEPINTVL 各个keepalive探测器之间的时间(以秒为单位)

特定于Linux的(2.6.37+)选项可影响TCP用户超时

TCP_USER_TIMEOUT 在TCP强行关闭连接之前,传输数据的最大时间(以毫秒为单位)可能仍未被确认.

因此,例如,您的应用程序可以使用此选项来确定连接在没有连接时存活多长时间(类似于您的NIC拔出示例).例如,如果你有理由相信客户会回来(也许他们关闭了笔记本电脑的盖子?参差不齐的无线接入?)你可以指定12小时的超时,当他们回来时,连接仍然会起作用.

  • 仅供参考,Linux 2.4+ 为“setsockopt()”提供了“TCP_KEEPIDLE”、“TCP_KEEPINTVL”和“TCP_KEEPCNT”选项,分别用于设置探测开始前的空闲时间、探测之间的时间间隔以及要发送的最大探测数量。 (3认同)