2011-12-12 137 views
4

connect()的失败对于TCP客户端连接()调用到TCP服务器..的Linux - TCP与ETIMEDOUT

由理查德·史蒂文斯UNIX®网络编程书上说,下面..

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

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

如果有人能指出我在代码中的位置,这个重试逻辑的实现也会有所帮助。我尝试了一下从net/ipv4/tcp_ipv4.c的tcp_v4_connect()开始,但很快就失去了我的方式。

回答

6

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

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将使用每个目的地re-transmission timeout;如果来自目的地的先前指标可以从以前的连接中获得,则重新使用它。 (详细内容请参阅tcp_no_metrics_save讨论tcp(7)。)如果没有指标保存,然后内核会回落到一个默认的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. 
               */ 

有接近底部的一些代码重新计算延迟:

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()将首先执行线性回退,然后执行指数回退。

我认为其中的很长一段时间是你可以合理地期待大约120秒之后得到ETIMEDOUT错误从connect(2)返回,除非内核有足够的理由怀疑远程对等方应该早些回复。

+0

谢谢..正是我在找什么。 – Manohar

3

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

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