对于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进行回复。
这是防止黑客探测主机网络的常见设置。