我打开一个 TCP 套接字并将其连接到网络上其他地方的另一个套接字。然后我可以成功发送和接收数据。我有一个计时器,它每秒向套接字发送一些东西。
然后我通过强行断开连接(在这种情况下拔出以太网电缆)粗鲁地中断连接。我的套接字仍在报告它每秒成功地写出数据。这将持续大约 1 小时 30 分钟,最终出现写入错误。
是什么指定了套接字最终接受另一端消失的超时?是操作系统(Ubuntu 11.04),是来自 TCP/IP 规范,还是套接字配置选项?
我打开一个 TCP 套接字并将其连接到网络上其他地方的另一个套接字。然后我可以成功发送和接收数据。我有一个计时器,它每秒向套接字发送一些东西。
然后我通过强行断开连接(在这种情况下拔出以太网电缆)粗鲁地中断连接。我的套接字仍在报告它每秒成功地写出数据。这将持续大约 1 小时 30 分钟,最终出现写入错误。
是什么指定了套接字最终接受另一端消失的超时?是操作系统(Ubuntu 11.04),是来自 TCP/IP 规范,还是套接字配置选项?
拉网线不会中断 TCP 连接(1),但会中断通信。您可以重新插入电缆,一旦建立 IP 连接,所有的备份数据都会移动。这就是使 TCP 可靠的原因,即使在蜂窝网络上也是如此。
当 TCP 发送数据时,它需要一个 ACK 作为回复。如果在一段时间内没有出现,它会重新传输数据并再次等待。它在传输之间等待的时间通常呈指数增长。
在一些重传次数或一些总时间没有 ACK 之后,TCP 将认为连接“断开”。多少次或多长时间取决于您的操作系统及其配置,但它通常会超时几分钟。
从 Linux 的tcp.7 手册页:
tcp_retries2 (integer; default: 15; since Linux 2.2)
The maximum number of times a TCP packet is retransmitted in
established state before giving up. The default value is 15, which
corresponds to a duration of approximately between 13 to 30 minutes,
depending on the retransmission timeout. The RFC 1122 specified
minimum limit of 100 seconds is typically deemed too short.
这可能是您想要调整的值,以更改检测连接是否消失所需的时间。
(1) 有例外。操作系统在注意到电缆被移除时,可以通知上层所有连接都应被视为“断开”。
如果想要快速将套接字错误传播到您的应用程序代码,您可能想尝试这个套接字选项:
TCP_USER_TIMEOUT(自 Linux 2.6.37 起)此选项采用无符号整数作为参数。当该值大于 0 时,它指定在 TCP 强制关闭相应连接并将ETIMEDOUT返回给应用程序之前,传输的数据可能保持未确认的最长时间(以毫秒为单位) 。如果选项值指定为 0,TCP 将使用系统默认值。
请参阅linux/man/tcp(7)上的完整描述。此选项比tcp_retries2编辑更灵活(您可以在创建套接字后立即设置它),并且完全适用于客户端的套接字不知道服务器的一种状态并且可能进入所谓的半-封闭状态。