我打开一个TCP套接字并将其连接到网络上其他位置的另一个套接字。然后,我可以成功发送和接收数据。我有一个定时器,每秒都会向套接字发送一些东西。
然后我通过强行断开连接(在这种情况下拉出以太网电缆)粗暴地中断连接。我的套接字仍然报告它每秒都成功写出数据。这将持续大约1小时30分钟,最终会出现写入错误。
什么指定套接字最终接受另一端的超时已消失?它是操作系统(Ubuntu 11.04),它来自TCP / IP规范,还是套接字配置选项?
答案 0 :(得分:66)
拉网线不会破坏TCP连接(1),但会中断通信。您可以重新插入电缆,一旦建立IP连接,所有后向数据都将移动。这就是使TCP可靠的原因,即使在蜂窝网络上也是如此。
当TCP发送数据时,它需要一个ACK作为回复。如果在一段时间内都没有,它会重新传输数据并再次等待。它在传输之间等待的时间通常会呈指数级增长。
经过一定数量的重传或一些没有ACK的总时间后,TCP会认为连接“已损坏”。多少次或多长时间取决于您的操作系统及其配置,但通常会在很长时间内超时。
来自Linux的tcp.7 man page:
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)这有例外。操作系统在注意到电缆被移除后,可以通知上层所有连接应被视为“损坏”。
答案 1 :(得分:0)
如果要将套接字错误快速传播到您的应用程序代码,则可以尝试使用以下套接字选项:
TCP_USER_TIMEOUT (从Linux 2.6.37开始) 此选项以 unsigned int 作为参数。当。。。的时候 值大于0,它指定最大数量 毫秒中的时间,表示传输的数据可能会保留 在TCP强制关闭 相应的连接,然后将 ETIMEDOUT 返回到 应用。如果选项值指定为0,TCP将 使用系统默认值。
请参阅linux/man/tcp(7)的完整说明。该选项比 tcp_retries2 编辑更加灵活(可以在创建套接字后立即进行设置),并且完全适用于客户端的套接字不知道服务器的一个状态和可能会进入所谓的半封闭状态。