1. 程式人生 > >TCP三次握手/四次揮手及其狀態分析

TCP三次握手/四次揮手及其狀態分析

前面CLOSE_WAIT狀態分析與TIME_WAIT狀態分析其實都是TCP斷開連線過程中的兩個狀態.本文繼續介紹下TCP連線三次握手,四次揮手的過程及其中間的狀態

三次握手原理:

第一次握手:客戶端傳送syn包(syn=j)到伺服器,等待伺服器確認.

第二次握手:伺服器收到syn包,必須確認(ack=j+1),同時自己傳送一個syn包(syn=k),即SYN+ACK包.

第三次握手:客戶端收到伺服器的SYN+ACK包,向伺服器傳送確認包(ack=k+1).

圖示:

CLINET -----          SYN(j)         ----- SERVER  

SERVER -----  ACK(j+1) SYN(k) ----- CLINET

CLINET -----         ACK(k+1)     ----- SERVER

客戶端傳送syn包,進入SYN_SEND狀態,伺服器收到sync包,進入SYN_RECV狀態.

客戶端收到伺服器端的SYN+ACK包進入ESTABLISHED狀態.

伺服器端收到客戶機端的ack包,進入ESTABLISHED狀態.

簡單的說:

客戶端問伺服器:你允許我和你建立連線麼?

伺服器端說:可以,那你也允許我和你建立連線麼?

客戶端說:可以.

於是,他們之間就建立起連線了.

四次分手原理:

由於TCP連線是全雙工的,因此每個方向都必須單獨進行關閉.這個原則是當一方完成它的資料傳送任務後就能傳送一個FIN來終止這個方向的連線.收到一個 FIN只意味著這一方向上沒有資料流動,一個TCP連線在收到一個FIN後仍能傳送資料.首先進行關閉的一方將執行主動關閉,而另一方執行被動關閉.

(1)客戶端A傳送一個FIN,用來關閉客戶A到伺服器B的資料傳送.

(2)伺服器B收到這個FIN,它發回一個ACK,確認序號為收到的序號加1.

(3)伺服器B關閉與客戶端A的連線,傳送一個FIN給客戶端A.

(4)客戶端A發回ACK報文確認,並將確認序號設定為收到序號加1.

圖示:

CLINET  ---   FIN  --- SERVER

SERVER ---   ACK  --- CLINET 

SERVER ---   FIN  --- CLINET 

CLINET  ---   ACK --- SERVER

客戶端主動關閉連線,傳送FIN包,進入FIN_WAIT_1狀態.接收端收到FIN包,進入CLOSE_WAIT狀態.

客戶端收到伺服器的ACK包,進入FIN_WAIT_2狀態.

伺服器傳送FIN包,進入LAST_ACK狀態.客戶端接收到FIN包,進入TIME_WAIT狀態

伺服器收到ACK包,進入CLOSED狀態.

簡單的說:

客戶端問伺服器:我們斷開連線吧?

伺服器端說:可以,我將不再接收你的資料.

伺服器端問伺服器:我將要跟你斷開連線了,可以吧?

客戶端說:可以.

客戶端說:可以.

於是,他們之間的連線就斷開了.

TCP連線正常建立和終止過程及對應狀態如圖:

這裡有個連線同時開啟的問題,跟前面文章中說的五元組問題一樣,很難出現,但如果指定本地和對方兩端的埠號還是能製造出這樣的情況.

兩端都是在SYN_SENT狀態下收到對方的SYN包而進入SYN_RCVD狀態,然後都會發送SYN+ACK包,當兩端都會收到該包時,狀態會變成ESTABLISHED.

圖示:

CLINET  ---        SYN     --- SERVER       SERVER  ---      SYN       --- CLINET 

SERVER ---   SYN+ACK  --- CLINET       CLINET   ---   SYN+ACK  --- SERVER  

TCP連線同時建立過程及對應狀態如圖:

繼續說下CLOSING狀態,當兩端幾乎同時關閉連線時,兩端都是在FIN_WAIT_1狀態下收到對方的FIN包,會進入CLOSING狀態.然後都會發送最後的ACK包.當兩端都會收到該包時,狀態會變成TIME_WAIT.

圖示:

CLINET  ---   FIN  --- SERVER       SERVER   ---   FIN  --- CLINET 

SERVER ---   ACK  --- CLINET       CLINET   ---   ACK  --- SERVER  

TCP連線同時關閉過程及對應狀態如圖:

還有個問題:為什麼建立連線協議是三次握手,而關閉連線卻是四次握手呢?

這是因為服務端的LISTEN狀態下的SOCKET當收到SYN報文的建連請求後,它可以把ACK和SYN(ACK起應答作用,而SYN起同步作用)放在一個報文裡來發送.但關閉連線時,當收到對方的FIN報文通知時,它僅僅表示對方沒有資料傳送給你了.但未必你所有的資料都全部發送給對方了,所以你可以未必會馬上會關閉SOCKET,也即你可能還需要傳送一些資料給對方之後,再發送FIN報文給對方來表示你同意現在可以關閉連線了,所以它這裡的ACK報文和FIN報文多數情況下都是分開發送的.