(轉)*Socket TIME_WAIT 問題Q&A
(轉)*Socket TIME_WAIT 問題Q&A
tcp/ip詳解的卷1有詳細介紹過tcp的相關內容,其中TIME_WAIT講得有點晦澀,今日找到一篇不錯的文章,特拿來分享一下。
netstat -n | awk '/^tcp/ {++state[$NF]} END {for(key in state) print key,"/t",state[key]}'
會得到類似下面的結果,具體數字會有所不同:
LAST_ACK 1
SYN_RECV 14
ESTABLISHED 79
FIN_WAIT1 28
FIN_WAIT2 3
CLOSING 5
TIME_WAIT 1669
狀態:描述
CLOSED:無連線是活動的或正在進行
LISTEN:伺服器在等待進入呼叫
SYN_RECV:一個連線請求已經到達,等待確認
SYN_SENT:應用已經開始,開啟一個連線
ESTABLISHED:正常資料傳輸狀態
FIN_WAIT1:應用說它已經完成
FIN_WAIT2:另一邊已同意釋放
ITMED_WAIT:等待所有分組死掉
CLOSING:兩邊同時嘗試關閉
TIME_WAIT:另一邊已初始化一個釋放
LAST_ACK:等待所有分組死掉
也就是說,這條命令可以把當前系統的網路連線狀態分類彙總。
下面解釋一下為啥要這樣寫:
一個簡單的管道符連線了netstat和awk命令。
------------------------------------------------------------------
每個TCP報文在網路內的最長時間,就稱為MSL(Maximum Segment Lifetime),它的作用和IP資料包的TTL類似。
RFC793指出,MSL的值是2分鐘,但是在實際的實現中,常用的值有以下三種:30秒,1分鐘,2分鐘。
注意一個問題,進入TIME_WAIT狀態的一般情況下是客戶端,大多數伺服器端一般執行被動關閉,不會進入TIME_WAIT狀態,當在服務
器端關閉某個服務再重新啟動時,它是會進入TIME_WAIT狀態的。
舉例:
1.客戶端連線伺服器的80服務,這時客戶端會啟用一個本地的埠訪問伺服器的80,訪問完成後關閉此連線,立刻再次訪問伺服器的
80,這時客戶端會啟用另一個本地的埠,而不是剛才使用的那個本地埠。原因就是剛才的那個連線還處於TIME_WAIT狀態。
2.客戶端連線伺服器的80服務,這時伺服器關閉80埠,立即再次重啟80埠的服務,這時可能不會成功啟動,原因也是伺服器的連
接還處於TIME_WAIT狀態。
檢查net.ipv4.tcp_tw當前值,將當前的值更改為1分鐘:
[root@aaa1 ~]# sysctl -a|grep net.ipv4.tcp_tw
net.ipv4.tcp_tw_reuse = 0
net.ipv4.tcp_tw_recycle = 0
[root@aaa1 ~]#
vi /etc/sysctl
增加或修改net.ipv4.tcp_tw值:
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
使核心引數生效:
[root@aaa1 ~]# sysctl -p
[root@aaa1 ~]# sysctl -a|grep net.ipv4.tcp_tw
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
用netstat再觀察正常
這裡解決問題的關鍵是如何能夠重複利用time_wait的值,我們可以設定時檢查一下time和wait的值
#sysctl -a | grep time | grep wait
net.ipv4.netfilter.ip_conntrack_tcp_timeout_time_wait = 120
net.ipv4.netfilter.ip_conntrack_tcp_timeout_close_wait = 60
net.ipv4.netfilter.ip_conntrack_tcp_timeout_fin_wait = 120
問一下TIME_WAIT有什麼問題,是閒置而且記憶體不回收嗎?
是的,這樣的現象實際是正常的,有時和訪問量大有關,設定這兩個引數: reuse是表示是否允許重新應用處於TIME-WAIT狀態的
socket用於新的TCP連線; recyse是加速TIME-WAIT sockets回收
Q: 我正在寫一個unix server程式,不是daemon,經常需要在命令列上重啟它,絕大
多數時候工作正常,但是某些時候會報告"bind: address in use",於是重啟失
敗。
A: Andrew Gierth
server程式總是應該在呼叫bind()之前設定SO_REUSEADDR套接字選項。至於
TIME_WAIT狀態,你無法避免,那是TCP協議的一部分。
Q: 如何避免等待60秒之後才能重啟服務
A: Erik Max Francis
使用setsockopt,比如
--------------------------------------------------------------------------
int option = 1;
if ( setsockopt ( masterSocket, SOL_SOCKET, SO_REUSEADDR, &option,
sizeof( option ) ) < 0 )
{
die( "setsockopt" );
}
--------------------------------------------------------------------------
Q: 編寫 TCP/SOCK_STREAM 服務程式時,SO_REUSEADDR到底什麼意思?
A: 這個套接字選項通知核心,如果埠忙,但TCP狀態位於 TIME_WAIT ,可以重用
埠。如果埠忙,而TCP狀態位於其他狀態,重用埠時依舊得到一個錯誤資訊,
指明"地址已經使用中"。如果你的服務程式停止後想立即重啟,而新套接字依舊
使用同一埠,此時 SO_REUSEADDR 選項非常有用。必須意識到,此時任何非期
望資料到達,都可能導致服務程式反應混亂,不過這只是一種可能,事實上很不
可能。
一個套接字由相關五元組構成,協議、本地地址、本地埠、遠端地址、遠端端
口。SO_REUSEADDR 僅僅表示可以重用本地本地地址、本地埠,整個相關五元組
還是唯一確定的。所以,重啟後的服務程式有可能收到非期望資料。必須慎重使
用 SO_REUSEADDR 選項。
Q: 在客戶機/伺服器程式設計中(TCP/SOCK_STREAM),如何理解TCP自動機 TIME_WAIT 狀
態?
A: W. Richard Stevens <1999年逝世,享年49歲>
下面我來解釋一下 TIME_WAIT 狀態,這些在<>
中2.6節解釋很清楚了。
MSL(最大分段生存期)指明TCP報文在Internet上最長生存時間,每個具體的TCP實現
都必須選擇一個確定的MSL值。RFC 1122建議是2分鐘,但BSD傳統實現採用了30秒。
TIME_WAIT 狀態最大保持時間是2 * MSL,也就是1-4分鐘。
IP頭部有一個TTL,最大值255。儘管TTL的單位不是秒(根本和時間無關),我們仍需
假設,TTL為255的TCP報文在Internet上生存時間不能超過MSL。
TCP報文在傳送過程中可能因為路由故障被迫緩衝延遲、選擇非最優路徑等等,結果
傳送方TCP機制開始超時重傳。前一個TCP報文可以稱為"漫遊TCP重複報文",後一個
TCP報文可以稱為"超時重傳TCP重複報文",作為面向連線的可靠協議,TCP實現必須
正確處理這種重複報文,因為二者可能最終都到達。
一個通常的TCP連線終止可以用圖描述如下:
client server
FIN M
close -----------------> (被動關閉)
ACK M+1
<-----------------
FIN N
<----------------- close
ACK N+1
----------------->
為什麼需要 TIME_WAIT 狀態?
假設最終的ACK丟失,server將重發FIN,client必須維護TCP狀態資訊以便可以重發
最終的ACK,否則會傳送RST,結果server認為發生錯誤。TCP實現必須可靠地終止連
接的兩個方向(全雙工關閉),client必須進入 TIME_WAIT 狀態,因為client可能面
臨重發最終ACK的情形。
{
scz 2001-08-31 13:28
先呼叫close()的一方會進入TIME_WAIT狀態
}
此外,考慮一種情況,TCP實現可能面臨先後兩個同樣的相關五元組。如果前一個連
接處在 TIME_WAIT 狀態,而允許另一個擁有相同相關五元組的連線出現,可能處理
TCP報文時,兩個連線互相干擾。使用 SO_REUSEADDR 選項就需要考慮這種情況。
為什麼 TIME_WAIT 狀態需要保持 2MSL 這麼長的時間?
如果 TIME_WAIT 狀態保持時間不足夠長(比如小於2MSL),第一個連線就正常終止了。
第二個擁有相同相關五元組的連線出現,而第一個連線的重複報文到達,干擾了第二
個連線。TCP實現必須防止某個連線的重複報文在連線終止後出現,所以讓TIME_WAIT
狀態保持時間足夠長(2MSL),連線相應方向上的TCP報文要麼完全響應完畢,要麼被
丟棄。建立第二個連線的時候,不會混淆。
A: 小四
在Solaris 7下有核心引數對應 TIME_WAIT 狀態保持時間
# ndd -get /dev/tcp tcp_time_wait_interval
240000
# ndd -set /dev/tcp tcp_time_wait_interval 1000
預設設定是240000ms,也就是4分鐘。如果用ndd修改這個值,最小隻能設定到1000ms,
也就是1秒。顯然核心做了限制,需要Kernel Hacking。
# echo "tcp_param_arr/W 0t0" | adb -kw /dev/ksyms /dev/mem
physmem 3b72
tcp_param_arr: 0x3e8 = 0x0
# ndd -set /dev/tcp tcp_time_wait_interval 0
我不知道這樣做有什麼災難性後果,參看<>的宣告。
Q: TIME_WAIT 狀態保持時間為0會有什麼災難性後果?在普遍的現實應用中,好象也
就是伺服器不穩定點,不見得有什麼災難性後果吧?
D: rain@bbs.whnet.edu.cn
核心原始碼 /usr/src/linux/include/net/tcp.h 中
#define TCP_TIMEWAIT_LEN (60*HZ) /* how long to wait to successfully
* close the socket, about 60 seconds */
最好不要改為0,改成1。埠分配是從上一次分配的埠號+1開始分配的,所以一般
不會有什麼問題。埠分配在tcp_ipv4.c中tcp_v4_get_port中。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/7728585/viewspace-2138692/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- [20230317]關於TIME_WAIT問題.txtAI
- 微軟內推常見問題 Q&A微軟
- Socket 粘包和分包問題
- Q&A:「微搭低程式碼」計費相關問題
- 25. Socket與粘包問題
- 【Socket】解決UDP丟包問題UDP
- socket 斷開和重連問題
- 解決Tengine健康檢查引起的TIME_WAIT堆積問題AI
- socket close和shutdown的區別,TIME_WAIT和CLOSE_WAIT,SO_REUSEADDRAI
- TF實戰Q&A丨這個問題,我以前也遇到過
- socket程式設計中常見的概念問題!程式設計
- socket的半包,粘包與分包的問題
- SystemedMiner再次更新,使用Socket5中轉訪問C&C
- oid轉blob問題
- mysql 轉義問題MySql
- Javaweb Q&AJavaWeb
- [轉載]什麼是P問題、NP問題和NPC問題
- 調整time_waitAI
- (轉)認清效能問題
- Q&A|聚焦《資料安全法》實施,企業資料安全建設常見問題
- 網路基礎問題整理:為什麼TCP四次揮手最後需要TIME_WAIT狀態?TCPAI
- 字串轉數字的問題字串
- (一) 溫度轉換問題
- Matlab轉python的索引問題MatlabPython索引
- 連結串列反轉問題
- mysql隱式轉換問題MySql
- 轉賬問題是屬於業務問題還是屬於技術問題?
- 重要說明 Q&A
- 面試 Q&A (一)面試
- 面試 Q&A (二)面試
- socket 實現的 web 伺服器在 Windows 下的讀寫問題Web伺服器Windows
- 轉載 ebpf sockmap/redirection 提升 socket 效能(2020)eBPF
- SAP交貨單迴轉問題
- 關於 a 標籤跳轉問題
- 反轉連結串列系列問題
- [轉帖]XACT_ABORT 的問題
- fastjson字串轉JSON的$ref問題ASTJSON字串
- Android Activity跳轉閃屏問題Android
- 【問題解決】使用YYYY-MM-dd時間轉換問題