Linux 建立 TCP 連線的超時時間分析

2021-08-15 03:26:13 字數 4409 閱讀 7932

linux 系統預設的建立 tcp 連線的超時時間為 127 秒,對於許多客戶端來說,這個時間都太長了, 特別是當這個客戶端實際上是乙個服務的時候,更希望能夠盡早失敗,以便能夠選擇其它的可用服務重新嘗試。

socket 是 linux 下實現的傳輸控制層協議,包括 tcp 和 udp,乙個 socket 端點由 ip 和埠對來唯一標識; 如果開啟了位址復用,那麼可以進一步由協議,ip 和埠來唯一標識。

系統呼叫 connect 則是用來嘗試建立 socket 連線(tcp),著名的 tcp 三次握手實際上也由 connect 來觸發完成的。

網路中的連線超時非常常見,所以連線加入了重試機制, 同時為了不給服務端帶來過大的壓力,重試也是有相應的策略,有一定的退避機制和重試次數。

在 linux 中,連線超時典型為 2 分 7 秒,而對於一些 client 來說,這是乙個非常長的時間; 所以在程式設計中,可以使用非阻塞的方式來實現,例如:使用 poll, epoll 等系統呼叫來實現多路復用等待。

下面來看看 2 分 7 秒是怎樣來的,以及怎樣配置 linux kernel 來縮短這個超時。

2 分 7 秒

2 分 7 秒即 127 秒,剛好是 2 的 7 次方減一,對數字敏感的讀者可能已經看出來了,如果 tcp 握手的 syn 包超時重試按照 2 的冪來退避, 那麼:

第 1 次傳送 syn 報文後等待 1s(2 的 0 次冪),如果超時,則重試

第 2 次傳送後等待 2s(2 的 1 次冪),如果超時,則重試

第 3 次傳送後等待 4s(2 的 2 次冪),如果超時,則重試

第 4 次傳送後等待 8s(2 的 3 次冪),如果超時,則重試

第 5 次傳送後等待 16s(2 的 4 次冪),如果超時,則重試

第 6 次傳送後等待 cr(2 的 5 次冪),如果超時,則重試

第 7 次傳送後等待 64s(2 的 6 次冪),如果超時,則超時失敗

上面的結果剛好是 127 秒。也就是說 linux 核心在嘗試建立 tcp 連線時,最多會嘗試 7 次。

# iptables -a input --protocol tcp --dport 5000 --syn -j drop 新增過濾
ps;別忘了用—d進行刪除;需要root許可權;

tcpdump,又該你上場了

# tcpdump -i lo -ss0 -n src 127.0.0.1 and dst 127.0.0.1 and port 5000
測試:

[matrix@localhost ~]$ date; telnet 127.0.0.1 5000; date

2023年 01月 24日 星期三 22:38:15 cst

trying 127.0.0.1...

telnet: connect to address 127.0.0.1: connection timed out

2023年 01月 24日 星期三 22:40:22 cst

[matrix@localhost ~]$

[matrix@localhost ~]$ sudo tcpdump -i lo 'tcp[tcpflags] = tcp-syn'

[sudo] password for matrix:

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode

listening on lo, link-type en10mb (ethernet), capture size 65535 bytes

22:38:15.825569 ip localhost.54464 > localhost.commplex-main: flags [s], seq 2345953452, win 32792, options [mss 16396,sackok,ts val 19650917 ecr 0,nop,wscale 7], length 0

22:38:16.825246 ip localhost.54464 > localhost.commplex-main: flags [s], seq 2345953452, win 32792, options [mss 16396,sackok,ts val 19651917 ecr 0,nop,wscale 7], length 0

22:38:18.825139 ip localhost.54464 > localhost.commplex-main: flags [s], seq 2345953452, win 32792, options [mss 16396,sackok,ts val 19653917 ecr 0,nop,wscale 7], length 0

22:38:22.825095 ip localhost.54464 > localhost.commplex-main: flags [s], seq 2345953452, win 32792, options [mss 16396,sackok,ts val 19657917 ecr 0,nop,wscale 7], length 0

22:38:30.825387 ip localhost.54464 > localhost.commplex-main: flags [s], seq 2345953452, win 32792, options [mss 16396,sackok,ts val 19665917 ecr 0,nop,wscale 7], length 0

22:38:46.825921 ip localhost.54464 > localhost.commplex-main: flags [s], seq 2345953452, win 32792, options [mss 16396,sackok,ts val 19681918 ecr 0,nop,wscale 7], length 0

22:39:18.826499 ip localhost.54464 > localhost.commplex-main: flags [s], seq 2345953452, win 32792, options [mss 16396,sackok,ts val 19713918 ecr 0,nop,wscale 7], length 0

怎樣修改 connect timeout

對於很多客戶端程式來說,127 秒都是乙個很長的時間,特別是對於區域網來說,公司內部往往都具有網路質量較好的區域網, 訪問內部的服務並不需要等待這麼長的超時,而可以 fail earlier。

linux 核心中,net.ipv4.tcp_syn_retries 表示建立 tcp 連線時 syn 報文重試的次數,預設為 6,可以通過 sysctl 命令檢視。

# sysctl -a | grep tcp_syn_retries

vim /etc/sysctl.conf

net.ipv4.tcp_syn_retries = 6

將其修改為 1,則可以將 connect 超時時間改為 3 秒,例如:

# sysctl net.ipv4.tcp_syn_retries=1

之後,sysctl -p /etc/sysctl.conf

再次使用 telnet 驗證超時時間,如下:

[matrix@localhost ~]$ date; telnet 127.0.0.1 5000; date

2023年 01月 24日 星期三 22:46:19 cst

trying 127.0.0.1...

telnet: connect to address 127.0.0.1: connection timed out

2023年 01月 24日 星期三 22:46:22 cst

[matrix@localhost ~]$ sudo tcpdump -i lo 'tcp[tcpflags] = tcp-syn'

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode

listening on lo, link-type en10mb (ethernet), capture size 65535 bytes

22:46:19.439704 ip localhost.54467 > localhost.commplex-main: flags [s], seq 3513959316, win 32792, options [mss 16396,sackok,ts val 20134532 ecr 0,nop,wscale 7], length 0

22:46:20.439675 ip localhost.54467 > localhost.commplex-main: flags [s], seq 3513959316, win 32792, options [mss 16396,sackok,ts val 20135532 ecr 0,nop,wscale 7], length 0

tcp連線超時處理

設定connect超時很簡單,csdn上也有人提到過使用select,但卻沒有乙個令人滿意與完整的答案。偶所講的也正是select函式,此函式整合在winsock1.1中,簡單點講,作用使那些想避免在套接字呼叫過程中被鎖定的應用程式,採取一種有序的方式,同時對多個套接字進行管理 windows網路程...

tcp中設定連線超時

直接上 設定連線超時 首先改成非阻塞套接字 unsigned long ul 1 int rm ioctl sconnect,fionbio,unsigned long ul if rm 1 向伺服器發出連線請求 int err connect sconnect,struct sockaddr ad...

TCP建立連線

3 月,跳不動了?對tcp 面向連線 特性的學習研究。什麼是面向連線?tcp為什麼要進行面向連線的通訊?tcp 連線建立的過程是怎樣的?建立連線的通訊過程 打 是面向連線的通訊 a 呼叫 b b 接受並且此時 a 還沒有結束通話,連線建立成功,a b 雙方正常通訊。如果 b 不接受呼叫,連線無法建立...