TCP三次握手和四次揮手


TCP三次握手

所謂三次握手(Three-Way Handshake)即建立TCP連接,就是指建立一個TCP連接時,需要客戶端和服務端總共發送3個包以確認連接的建立。整個流程如下圖所示:

TCP三次握手

  1. 第一次握手:Client將標志位SYN置為1,隨機產生一個值seq=J,並將該數據包發送給Server,Client進入SYN_SENT狀態,等待Server確認。
  2. 第二次握手:Server收到數據包后由標志位SYN=1知道Client請求建立連接,Server將標志位SYN和ACK都置為1,ack=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之間可以開始傳輸數據了。

為什么需要三次握手,而不是二次握手?

主要是為了防止兩次握手情況下已失效的連接請求報文段突然又傳送到服務端,而產生的錯誤。舉例如下:

Client向Server發出TCP連接請求,第一個連接請求報文在網絡的某個節點長時間滯留,Client超時后認為報文丟失,於是再重傳一次連接請求,Server收到后建立連接。數據傳輸完畢后雙方斷開連接。而此時,前一個滯留在網絡中的連接請求到達了服務端Server,而Server認為Client又發來連接請求,若采用的是“兩次握手”,則這種情況下Server認為傳輸連接已經建立,並一直等待Client傳輸數據,而Client此時並無連接請求,因此不予理睬,這樣就造成了Server的資源白白浪費了;但此時若是使用“三次握手”,則Server向Client返回確認報文段,由於是一個失效的請求,因此Client不予理睬,建立連接失敗。第三次握手的作用:防止已失效的連接請求報文段突然又傳送到了服務器。

第三次握手失敗后怎么處理?

如果此時ACK在網絡中丟失,那么Server端該TCP連接的狀態為SYN_RECV,並且依次等待3秒、6秒、12秒后重新發送SYN+ACK包,以便Client重新發送ACK包,以便Client重新發送ACK包。

Server重發SYN+ACK包的次數,可以通過設置/proc/sys/net/ipv4/tcp_synack_retries修改,默認值為5。

如果重發指定次數后,仍然未收到ACK應答,那么一段時間后,Server自動關閉這個連接。但是Client認為這個連接已經建立,如果Client端向Server寫數據,Server端將以RST包響應,方能感知到Server的錯誤。

TCP四次揮手(Client或Server均可主動發起揮手動作)

所謂四次揮手(Four-Way Wavehand)即終止TCP連接,就是指斷開一個TCP連接時,需要客戶端和服務端總共發送4個包以確認連接的斷開。整個流程如下圖所示:

TCP四次揮手

  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在LISTEN狀態下,收到建立連接請求的SYN報文后,可以直接把ACK和SYN放在一個報文里發送給Client。而關閉連接時,當收到對方的FIN報文時,僅僅表示對方不再發送數據了但是還能接收數據,己方也未必全部數據都發送給對方了,所以己方可以立即close,也可以發送一些數據給對方后,再發送FIN報文給對方來表示同意現在關閉連接,因此,己方ACK和FIN一般都會分開發送。

為什么TIME_WAIT狀態需要經過2MSL(最大報文段生存時間)才能返回到CLOSE狀態?

  1. Client的最后一個ACK報文在傳輸的時候丟失,Server並沒有接收到這個報文。這個時候,Server就會超時重傳這個FIN消息,然后Client就會重新返回最后一個ACK報文,等待兩個時間周期,完成關閉。如果不等待這兩個時間周期,Server重傳的那條消息就不會收到。Server就因為接收不到Client的信息而無法正常關閉。
  2. 防止“已失效的連接請求報文段”出現在本連接中。在發送完最后一個ACK報文段后,再經過2MSL,就可以使本連接持續的時間內所產生的所有報文段,都從網絡中消失。這樣就可以使下一個新的連接中不會出現這種就得連接請求報文段。


免責聲明!

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



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