1. 程式人生 > >TCP連線和關閉的過程

TCP連線和關閉的過程

轉載的連結處:TCP連線和關閉
建立連線:三次握手
在 TCP/IP 協議中,TCP 協議提供可靠的連線服務,採用三次握手建立一個連線,如圖1所示。
這裡寫圖片描述
圖1 TCP三次握手建立連線的過程

  1. 客戶端 A 傳送 SYN 包(SYN=j)到伺服器 B,並進入SYN_SEND 狀態,等待伺服器 B 確認。
  2. 伺服器 B 收到 SYN 包,必須確認客戶 A 的 SYN(ACK=j+1),同時自己也傳送一個 SYN 包(SYN=k),即 ACK+SYN 包,此時伺服器 B 進入SYN_RECV 狀態。
  3. 客戶端 A 收到伺服器 B 的 SYN+ACK 包,向伺服器 B 傳送確認包 ACK(ACK=k+1)。此包傳送完畢,客戶端 A 和伺服器 B 進入 ESTABLISHED 狀態,完成三次握手。
    完成三次握手,客戶端與伺服器開始傳送資料。

斷開連線:四次揮手
由於 TCP 連線是全雙工的,因此每個方向都必須單獨進行關閉。
這個原則是當一方完成它的資料傳送任務後就能傳送一個 FIN 來終止這個方向的連線。
收到一個 FIN 只意味著這一方向上沒有資料流動,一個 TCP 連線在收到一個 FIN 後仍能傳送資料。
首先進行關閉的一方將執行主動關閉,而另一方執行被動關閉。
TCP採用四次揮手關閉連線如圖2所示。
這裡寫圖片描述

  1. 客戶端 A 傳送一個 FIN,用來關閉客戶 A 到伺服器 B 的資料傳送。
  2. 伺服器 B 收到這個 FIN,它發回一個 ACK,確認序號為收到的序號加1。和 SYN 一樣,一個 FIN 將佔用一個序號。
  3. 伺服器 B 關閉與客戶端 A 的連線,傳送一個 FIN 給客戶端 A。
  4. 客戶端 A 發回 ACK 報文確認,並將確認序號設定為收到序號加1。

FAQ
1.為什麼建立連線協議是三次握手,而關閉連線卻是四次握手呢?
這是因為服務端的 LISTEN 狀態下的 SOCKET 當收到 SYN 報文的建連請求後,它可以把 ACK 和 SYN(ACK 起應答作用,而 SYN 起同步作用)放在一個報文裡來發送。
但關閉連線時,當收到對方的 FIN 報文通知時,它僅僅表示對方沒有資料傳送給你了;但未必你所有的資料都全部發送給對方了,所以你未必會馬上會關閉 SOCKET,也即你可能還需要傳送一些資料給對方之後,再發送 FIN 報文給對方來表示你同意現在可以關閉連線了,所以它這裡的 ACK 報文和 FIN 報文多數情況下都是分開發送的。
2.為什麼 TIME_WAIT 狀態還需要等 2MSL 後才能返回到 CLOSED 狀態?
這是因為雖然雙方都同意關閉連線了,而且握手的4個報文也都協調和傳送完畢,按理可以直接回到 CLOSED 狀態(就好比從 SYN_SEND 狀態到 ESTABLISH 狀態那樣);但是因為我們必須要假想網路是不可靠的,你無法保證你最後傳送的 ACK 報文會一定被對方收到,因此對方處於 LAST_ACK 狀態下的 SOCKET 可能會因為超時未收到 ACK 報文,而重發 FIN 報文,所以這個 TIME_WAIT 狀態的作用就是用來重發可能丟失的 ACK 報文。

參考
《TCP/IP詳解-卷1》第18章《TCP連線的建立與終止》
《UNIX網路程式設計-卷1》第2.6節《TCP連線的建立和終止》

《TCP連線的狀態轉換圖深度剖析》

《TCP狀態轉換圖》
《傳輸控制協議(TCP) – TCP狀態轉換圖》
《TCP狀態轉換圖、滑動視窗、半連線狀態、2MSL》