TCP的三次握手/四次揮手 詳解

三次握手的過程:

TCP 連接是通過三次握手進行初始化的。三次握手的目的是同步連接雙方的序列號和確認號並交換 TCP 窗口大小信息。

    1. 客戶端向服務器發送一個SYN置位的TCP報文,其中包含連接的初始序列號x和一個窗口大小(表示客戶端上用來接收從服務器發送來的傳入段的緩衝區的大小)。

    2. Server收到數據包後由標誌位SYN=1知道Client請求建立連接

       Server將標誌位SYN和ACK都置爲1,ack (number )=J+1,隨機產生一個值seq=K,並將該數據包發送給Client以確認連接請求,Server進入SYN_RCVD狀態。

    3.Client收到確認後,檢查ack是否爲J+1,ACK是否爲1

       如果正確則將標誌位ACK置爲1,ack=K+1,並將該數據包發送給Server,Server檢查ack是否爲K+1,ACK是否爲1,

       如果正確則連接建立成功,Client和Server進入ESTABLISHED狀態,完成三次握手,隨後Client與Server之間可以開始傳輸數據了

 

四次揮手過程

(1)Client發送一個FIN,用來關閉Client到Server的數據傳送,Client進入FIN_WAIT_1狀態。

(2)Server收到FIN後,發送一個ACK給Client,確認序號爲收到序號+1(與SYN相同,一個FIN佔用一個序號),Server進入CLOSE_WAIT狀態。

(3)Server發送一個FIN,用來關閉Server到Client的數據傳送,Server進入LAST_ACK狀態

(4)Client收到FIN後,Client進入TIME_WAIT狀態,接着發送一個ACK給Server,確認序號爲收到序號+1,Server進入CLOSED狀態,完成四次揮手。

  爲什麼連接的時候是三次握手,關閉的時候卻是四次握手?

答:因爲當Server端收到Client端的SYN連接請求報文後,可以直接發送SYN+ACK報文。其中ACK報文是用來應答的,SYN報文是用來同步的。

        但是關閉連接時,當Server端收到FIN報文時,很可能並不會立即關閉SOCKET,所以只能先回復一個ACK報文,告訴Client端,"你發的FIN報文我收到了"。

        只有等到Server端所有的報文都發送完了,我才能發送FIN報文,因此不能一起發送。故需要四步握手。

爲什麼不能用兩次握手進行連接?

答:3次握手完成兩個重要的功能,既要雙方做好發送數據的準備工作(雙方都知道彼此已準備好),也要允許雙方就初始序列號進行協商,這個序列號在握手過程中被髮送和確認。

        1. TCP的三次握手最主要是防止已過期的連接再次傳到被連接的主機。因爲client處於CLOSED狀態,接受到任何包都會丟棄.而此時的server還一直在等待client的數據

        2. 三次握手改成僅需要兩次握手,死鎖是可能發生

                即服務器返回的數據在傳輸過程中丟失了,那麼客戶端規定時間內沒收到就會超時重傳,則會發生死鎖.

如何理解TIME_WAIT狀態

首先調用close()發起主動關閉的一方,在發送最後一個ACK之後會進入time_wait的狀態,也就說該發送方會保持2MSL時間之後纔會回到初始狀態。MSL值得是數據包在網絡中的最大生存時間。產生這種結果使得這個TCP連接在2MSL連接等待期間,定義這個連接的四元組(客戶端IP地址和端口,服務端IP地址和端口號)不能被使用

爲什麼會有這個TIME_WAIT狀態

1)爲實現TCP全雙工連接的可靠釋放

        由TCP狀態變遷圖可知,假設發起主動關閉的一方(client)最後發送的ACK在網絡中丟失,由於TCP協議的超時重傳機制,執行被動關閉的一方(server)將會重發其FIN在該FIN到達client之前,client必須維護這條連接狀態,也就說這條TCP連接所對應的資源(client方的local_ip,local_port)不能被立即釋放或重新分配,直到另一方重發的FIN達到之後,client重發ACK後,經過2MSL時間週期沒有再收到另一方的FIN之後,該TCP連接才能恢復初始的CLOSED狀態。

如果主動關閉一方不維護這樣一個TIME_WAIT狀態,那麼當被動關閉一方重發的FIN到達時,主動關閉一方的TCP傳輸層會用RST包響應對方,這會被對方認爲是有錯誤發生,然而這事實上只是正常的關閉連接過程,並非異常。

2)使舊的數據包在網絡因過期而消失

     假設TCP協議中不存在TIME_WAIT狀態的限制,再假設當前有一條TCP連接:(local_ip, local_port, remote_ip,remote_port),因某些原因關閉它,接着很快以相同的四元組建立一條新連接

        因爲TCP連接由四元組唯一標識,因此,在這種情況中,TCP協議棧是無法區分前後兩條TCP連接的區別,在它看來,這根本就是同一條連接

        這樣就可能發生這樣的情況:前一條TCP連接的過期數據發送給對端之後,會被該當做正常數據接收並向上傳遞至應用層,從而引起數據錯亂進而導致各種無法預知的詭異現象。

        作爲一種可靠的傳輸協議,TCP必須在協議層面考慮並避免這種情況的發生,這正是TIME_WAIT狀態存在的第2個原因。

TIME_WAIT狀態如何避免

首先服務器可以設置SO_REUSEADDR套接字選項來通知內核,如果端口忙,但TCP連接位於TIME_WAIT狀態時可以重用端口。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章