關於TCP連接狀態的解釋


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

 

1、TCP建立連接時的三次握手:

 

服務端應用監聽端口處於LISTEN狀態,等待建立連接。

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

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

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

服務端和客戶端都進入ESTABLISHED狀態后,表示連接建立完成,可以傳輸數據。

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

 

 

2、TCP斷開連接時的四次揮手:

 

TCP連接中的任一端都可以主動斷開連接,應用中一般是客戶端主動斷開。

第一次揮手:客戶端向服務器端發送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 時間;

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM