Linux – TCP连接()与ETIMEDOUT失败

对于TCP客户端connect()调用TCP服务器..

Richard Stevens编写的UNIX®networking编程书说以下内容。

如果客户端TCP没有收到其SYN段的响应,则返回ETIMEDOUT。 例如,4.4BSD在连接被调用时发送一个SYN,另外6秒钟后,另一个24秒钟后(TCPv2的828页)发送。 如果总共75秒后没有收到响应,则返回错误。

在Linux中,我想知道什么是重试机制(多less次和多远)。 问一个TCP客户端connect()调用,我得到ETIMEDOUT错误。 该套接字具有O_NONBLOCK选项,并由epoll()监视事件。

如果有人可以指向我的代码这个重试逻辑的实现,这也将有所帮助。 我尝试了从net / ipv4 / tcp_ipv4.c的tcp_v4_connect()开始,但很快就失去了我的方式。

超时根据测量的往返时间进行缩放。

tcp_connect()设置一个定时器:

  /* Timer for repeating the SYN until an answer. */ inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, inet_csk(sk)->icsk_rto, TCP_RTO_MAX); 

icsk_rto将使用每个目的地的重新传输超时 ; 如果来自目的地的先前指标可从以前的连接中获得,则重新使用它。 (有关详细信息,请参阅tcp(7)tcp_no_metrics_save讨论。)如果未保存度量标准,则内核将回退到默认的RTO值:

 #define TCP_RTO_MAX ((unsigned)(120*HZ)) #define TCP_RTO_MIN ((unsigned)(HZ/5)) #define TCP_TIMEOUT_INIT ((unsigned)(1*HZ)) /* RFC2988bis initial RTO value */ #define TCP_TIMEOUT_FALLBACK ((unsigned)(3*HZ)) /* RFC 1122 initial RTO value, now * used as a fallback RTO for the * initial data transmission if no * valid RTT sample has been acquired, * most likely due to retrans in 3WHS. */ 

tcp_retransmit_timer()在底部附近有一些代码用于重新计算延迟:

  inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, icsk->icsk_rto, TCP_RTO_MAX); if (retransmits_timed_out(sk, sysctl_tcp_retries1 + 1, 0, 0)) __sk_dst_reset(sk); 

retransmits_timed_out()将首先执行线性退避,然后是指数退避。

我认为,从connect(2)得到ETIMEDOUT错误之前,除非内核有足够的理由怀疑远程对等方应该尽快回复,否则你可以合理地期待大约120秒。

ETIMEOUT的一个典型原因是防火墙只是简单地吞下数据包,而不是用ICMP Destination Unreachable进行回复。

这是防止黑客探测主机网络的常见设置。