關於TCP鏈接狀態的解釋

TCP各個狀態主要存在於三次握手和四次揮手的過程vim

 

一、TCP創建鏈接時的三次握手:服務器

 

服務端應用監聽端口處於LISTEN狀態,等待創建鏈接。cookie

第一次握手:客戶端發送SYN=一個隨機數,而後進入SYN_SENT狀態。網絡

第二次握手:服務端收到SYN後,向客戶端迴應ACK=隨機數+1,同時發送SYN=k,而後進入SYN_RCVD狀態。ssh

第三次握手:客戶端收到ACK後進行驗證,並回應SYN,返回ACK=k+1,而後進入ESTABLISHED狀態,服務端收到該ACK後進行驗證,而後也進入ESTABLISHED狀態。socket

服務端和客戶端都進入ESTABLISHED狀態後,表示鏈接創建完成,能夠傳輸數據。tcp

tcpdump抓包三次握手過程:優化

14:42:00.167658 IP 1.2.3.4.35646 > 192.168.1.223.ssh: Flags [S], seq 1012495606, win 29200, options [mss 1460,sackOK,TS val 3535567886 ecr 0,nop,wscale 7], length 0
14:42:00.167700 IP 192.168.1.223.ssh > 1.2.3.4.35646: Flags [S.], seq 1306417285, ack 1012495607, win 28960, options [mss 1460,sackOK,TS val 3639018129 ecr 3535567886,nop,wscale 7], length 0
14:42:00.169637 IP 1.2.3.4.35646 > 192.168.1.223.ssh: Flags [.], ack 1, win 229, options [nop,nop,TS val 3535567889 ecr 3639018129], length 0

 

 

二、TCP斷開鏈接時的四次揮手:spa

 

TCP鏈接中的任一端均可以主動斷開鏈接,應用中通常是客戶端主動斷開。code

第一次揮手:客戶端向服務器端發送FIN,表示要斷開鏈接(客戶端再也不發送數據了),而後進入FIN_WAIT_1狀態。

第二次揮手:服務端收到FIN後,迴應ACK,而後進入CLOSE_WAIT狀態。此時,服務端只能發送數據,不能接收數據。等服務端將緩衝區的數據發送完成後,向客戶端發送FIN,而後進入LAST_ACK狀態。

第三次揮手:客戶端收到FIN的ACK後,進入FIN_WAIT_2狀態,此時客戶端沒法再發送數據,只能接收數據。客戶端收到服務端發來的FIN(表示服務端已將緩衝區的數據發送完成),向服務端迴應ACK(確認客戶端已經收到該FIN),而後客戶端進入TIME_WAIT狀態。

第四次揮手:服務端收到ACK後,也進入TIME_WAIT狀態,客戶端進入TIME_WAIT狀態後,在等待等待2*MSL時間,進入CLOSED狀態,鏈接關閉。

tcpdump抓包四次揮手過程: 

14:42:19.284169 IP 1.2.3.4.ssh > 192.168.1.223.35646: Flags [F.], seq 41, ack 7, win 227, options [nop,nop,TS val 3639037245 ecr 3535587003], length 0
14:42:19.285929 IP 192.168.1.223.35646 > 1.2.3.4.ssh: Flags [.], ack 41, win 229, options [nop,nop,TS val 3535587005 ecr 3639037245], length 0
14:42:19.285986 IP 192.168.1.223.35646 > 1.2.3.4.ssh: Flags [F.], seq 7, ack 42, win 229, options [nop,nop,TS val 3535587005 ecr 3639037245], length 0
14:42:19.285998 IP 1.2.3.4.ssh >192.168.1.223.35646: Flags [.], ack 8, win 227, options [nop,nop,TS val 3639037247 ecr 3535587005], length 0

 

爲啥創建鏈接的時候是三次握手,而關閉鏈接的時候是四次揮手呢???

答:服務端在收到客戶端請求鏈接鏈接(SYN)的時候,能夠將SYN和ACK一塊兒發送(放到一個報文中發送)。

  服務端在收到客戶端發來的FIN請求關閉鏈接的時候,僅表示客戶端已沒有數據發送了,可是服務端可能還有沒發送完的數據,因此在迴應ACK以後,還要等到將全部的數據發送完畢後,再向客戶端迴應一個FIN,確承認以關閉鏈接。

 

 

關於MSL時間:

      MSL是Maximum Segment Lifetime英文的縮寫,中文能夠譯爲「報文最大生存時間」,他是任何報文在網絡上存在的最長時間,超過這個時間報文將被丟棄。由於tcp報文(segment)是ip數據報(datagram)的數據部分,具體稱謂請參見《數據在網絡各層中的稱呼》一文,而ip頭中有一個TTL域,TTL是time to live的縮寫,中文能夠譯爲「生存時間」,這個生存時間是由源主機設置初始值但不是存的具體時間,而是存儲了一個ip數據報能夠通過的最大路由數,每通過一個處理他的路由器此值就減1,當此值爲0則數據報將被丟棄,同時發送ICMP報文通知源主機。RFC 793中規定MSL爲2分鐘,實際應用中經常使用的是30秒,1分鐘和2分鐘等。 2MSL即兩倍的MSL,TCP的TIME_WAIT狀態也稱爲2MSL等待狀態,當TCP的一端發起主動關閉,在發出最後一個ACK包後,即第3次握手完成後發送了第四次握手的ACK包後就進入了TIME_WAIT狀態,必須在此狀態上停留兩倍的MSL時間,等待2MSL時間主要目的是怕最後一個ACK包對方沒收到,那麼對方在超時後將重發第三次握手的FIN包,主動關閉端接到重發的FIN包後能夠再發一個ACK應答包。在TIME_WAIT狀態時兩端的端口不能使用,要等到2MSL時間結束纔可繼續使用。當鏈接處於2MSL等待階段時任何遲到的報文段都將被丟棄。不過在實際應用中能夠經過設置SO_REUSEADDR選項達到沒必要等待2MSL時間結束再使用此端口。 TTL與MSL是有關係的但不是簡單的相等的關係,MSL要大於等於TTL。

 

查看系統中當前全部鏈接狀態:

netstat -n|awk '/^tcp/{++S[$NF]}END{for (key in S) print key,S[key]}'

TIME_WAIT 4976
CLOSE_WAIT 46
SYN_SENT 3
FIN_WAIT2 1
ESTABLISHED 405

發現TIME_WAIT狀態仍是比較多的,能夠經過調整內核參數優化:

#vim /etc/sysctl.conf

net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 30

net.ipv4.tcp_syncookies = 1 表示開啓SYN Cookies。當出現SYN等待隊列溢出時,啓用cookies來處理,可防範少許SYN攻擊,默認爲0,表示關閉;net.ipv4.tcp_tw_reuse = 1 表示開啓重用。容許將TIME_WAIT sockets從新用於新的TCP鏈接,默認爲0,表示關閉;net.ipv4.tcp_tw_recycle = 1 表示開啓TCP鏈接中TIME_WAIT sockets的快速回收,默認爲0,表示關閉;net.ipv4.tcp_fin_timeout 修改系默認的 TIMEOUT 時間;

相關文章
相關標籤/搜索