TCP 連線的建立和終止
TCP連線的建立
三次握手
- 伺服器端準備好接收外來的連結,通過該socket、bind、listen3個函式完成,為被動開啟
- 客戶端通過connect函式主動建立連線,通過傳送一個SYN(帶序號)
- 伺服器確認(ACK)客戶的SYN,確認序號為服務SYN的序號加1,同時傳送一個SYN(帶序號)
- 客戶端確認(ACK)服務的SYn,確認序號為服務SYN的序號加1.
如上就是我們通常所說的三次握手
TCP連線的終止
四次握手
- Client呼叫close主動關閉(通常是Client,也可以是server)。傳送一個FIN(帶序號)。進入FI_WAIT1狀態
- 接收到FIN的對端執行被動關閉。傳送ACK確認。然後進入CLOSE_WAIT。對端接收到ACK進入FIN_WAIT_2。此時為單方向關閉。
- 對端呼叫close執關閉。傳送FIN(帶序號)。進入LAST_ACK狀態。
- 接收到FIN的client傳送ACK確認,進入TIME_WAIT狀態。
- Server接收到ACK之後進入CLOSED狀態。完成連線的關閉。
如上為連線關閉的四次握手。
CLOSE_WAIT
Server接收到Client的FIN回覆ACK之後進入CLOSE_WAIT狀態。此時Client到Server的連線關閉。Client不能向Server傳送資料。而此時Server仍可以向Client傳送資料。
即此時為單向的連線關閉。需要Server也執行close關閉,才能轉入之後的狀態。
有時我們發現server有大量的close_wait,原因就是對方關閉了連線,而這邊由於忙於讀寫或其他原因,沒有執行關閉。
TIME_WAIT
Client端接收到Server的FIN傳送相應的ACK之後,進入TIME_WAIT狀態。該狀態的持續時間最長為MSL(maximum segment lifetime)的兩倍,即2MSL。
RFC1122的建議值為2分鐘,而Berkeley的傳統實現為30秒。所以其持續時間在1分鐘到4分鐘之間。
其存在是為了保證最後的ACK可以成功達到。否則會在MSL之後,Server重新發送FIN,從而觸發其重新發送ACK。最長為2MSL的時間。這個是最主要的理由。
還有一個理由是允許老的重複segment在網路中消逝:
考慮如下一個場景,在A的埠port1和B的埠port2建立了TCP連線,然後關閉了連線。為了保證過一段時間,我們還可以在A的埠port1和B的埠port2之間可以
建立連線。我們應該避免之前的在該連線上的老的分組再出現。為做到這一點,TCP不給處於TIME_WAIT狀態的連線發起新的連線。TIME_WAIT的狀態持續時間為2MSL,
這樣每個方向上的資料的最大存活時間為MSL。這樣保證成功建立一個TCP連線時,來自該連線的先前的老的重複分組都已經在網路中消逝了。