前面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連接正常建立和終止過程及對應狀態如圖:
http://hi.csdn.net/space-4175647-do-album-picid-512430.html
這裏有個連接同時打開的問題,跟前面文章中說的五元組問題一樣,很難出現,但如果指定本地和對方兩端的端口號還是能製造出這樣的情況.
兩端都是在SYN_SENT狀態下收到對方的SYN包而進入SYN_RCVD狀態,然後都會發送SYN+ACK包,當兩端都會收到該包時,狀態會變成ESTABLISHED.
圖示:
CLINET --- SYN --- SERVER SERVER --- SYN --- CLINET
SERVER --- SYN+ACK --- CLINET CLINET --- SYN+ACK --- SERVER
TCP連接同時建立過程及對應狀態如圖:
http://hi.csdn.net/space-4175647-do-album-picid-512432.html
繼續說下CLOSING狀態,當兩端幾乎同時關閉連接時,兩端都是在FIN_WAIT_1狀態下收到對方的FIN包,會進入CLOSING狀態.然後都會發送最後的ACK包.當兩端都會收到該包時,狀態會變成TIME_WAIT.
圖示:
CLINET --- FIN --- SERVER SERVER --- FIN --- CLINET
SERVER --- ACK --- CLINET CLINET --- ACK --- SERVER
TCP連接同時關閉過程及對應狀態如圖:
http://hi.csdn.net/space-4175647-do-album-picid-512433.html
還有個問題:爲什麼建立連接協議是三次握手,而關閉連接卻是四次握手呢?
這是因爲服務端的LISTEN狀態下的SOCKET當收到SYN報文的建連請求後,它可以把ACK和SYN(ACK起應答作用,而SYN起同步作用)放在一個報文裏來發送.但關閉連接時,當收到對方的FIN報文通知時,它僅僅表示對方沒有數據發送給你了.但未必你所有的數據都全部發送給對方了,所以你可以未必會馬上會關閉SOCKET,也即你可能還需要發送一些數據給對方之後,再發送FIN報文給對方來表示你同意現在可以關閉連接了,所以它這裏的ACK報文和FIN報文多數情況下都是分開發送的.
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/ustcgy/archive/2010/03/08/5356911.aspx