【計算機網絡】三次握手與四次揮手

三次握手與四次揮手

通過TCP/IP協議的學習,我們可以知道TCP協議是一種面向連接的、可靠的傳輸協議。其中,爲了保證客戶端與服務器連接的有效性,就有了本篇文章所要介紹的「三次揮手」;而「四次揮手」則是爲了保證連接的正確斷開。

1. TCP狀態

首先,介紹一下TCP的幾個狀態:

  • SYN —— 同步序列編號,在建立連接時發送
  • ACK —— 確認信息,在確認SYN信息時發送,響應信息
  • FIN —— 關閉連接
  • RST —— 連接重置
  • PSH —— 有數據傳輸
  • URG —— 緊急指針字段值有效

2. 三次握手

建立TCP連接時會經過如下步驟:

  • 服務器準備接收客戶端連接(通過socket API),由於連接是由客戶端激發的,因此稱爲被動打開
  • 客戶端調用connect開始主動打開,併發送SYN(syn = i)包,告訴服務器發送數據的序列號
  • 服務器確認(ACK,ack = i+1)客戶端發來的信息(SYN),併發送SYN(syn = j),其中含有服務器發送數據的初始序列號。注:SYNACK是同時發送的,在一個數據包中
  • 客戶端確認服務器發送的SYN,發送ACK(ack = j+1)數據包

其中,因爲SYN需要佔據一個字節的序列號空間,因此ACK中確認號爲發來的SYN序列號加1;類似,FIN的ACK確認號爲該FIN序列號加1。

1

3. 四次揮手

  • 某進程先調用close,該端TCP發送FIN(fin = i),表示數據發送完畢,需要關閉連接。稱爲主動關閉
  • 接收到FIN的對端執行被動關閉。進行確認(ACK, ack = i+1),在該進程接收的其他所有數據之後添加文件結束符(end-of-file)
  • 一段時間之後(因爲要處理已經接收到的數據),接收到文件結束符的進程調用close關閉套接字,這導致它的TCP也發送FIN(fin = j)
  • 主動關閉連接的一端確認(ACK, ack = j+1)最後發送的FIN

2

爲什麼建立連接要三次握手,而斷開連接要四次揮手?

建立連接時,因爲發起連接的一端在發出請求後,連接建立之前,就不會再發出任何數據,因此接收連接請求的對端可以將ACK、SYN放在一個數據包裏發回給請求端,即需要三次數據發送。而斷開連接時,在一端主動斷開連接併發送FIN包後,對端接收到發來的FIN包,進行確認(ACK),然而此時服務器可能還在給另一端發送數據,只有在數據發送完後才能斷開連接,發送FIN包(所以不能像三次握手時那樣將ACK、SYN同時發送),另一端收到FIN後再進行確認併發送ACK,因此需要四次數據發送。

TCP建立的連接爲全雙工通道,可以雙向傳輸數據,因此在建立連接、斷開連接時,需要兩端都要進行請求與確認。

爲什麼建立連接的ACK、SYN可以同時發送,而斷開連接則需要分開發送?

建立、斷開連接都需要兩次請求與確認,只是建立連接時SYN、ACK可以同時發回,而在斷開連接時,由於被動關閉的一端可能還會發送數據,只有數據發完後才能發送ACK,所以只能分開發送,也就造成了建立連接爲三次,斷開連接反而成了四次。(建立連接時由於握手期間連接未完全建立,故不能發送其他數據)