2011-12-12 363 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

這是防止黑客探測主機網絡的常用設置。