1. 程式人生 > 其它 >詳解TCP四次揮手(斷開TCP連線過程)

詳解TCP四次揮手(斷開TCP連線過程)

在講述TCP四次揮手,即斷開TCP連線的過程之前,需要先介紹一下TCP協議的包結構。
TCP協議包結構

這裡只對涉及到四次揮手過程的欄位做解釋

(1) 序號(Sequence number)
我們通過 TCP 協議將資料傳送給對方,就比如 hellotcp,這一串位元組流,假設被拆分成了三個 TCP 報文段,第一個報文段攜帶了 hel,第二個報文段攜帶了 lot,第三個報文段攜帶了 cp,這三個報文段不一定是按照順序送到對端的,那麼對端收到這三個段是如何確定他們的順序的呢?此時序號的意義就體現在這裡。

TCP 連線中,為傳送的位元組流(資料)中的每一個位元組按順序編號。也就是說,在一次 TCP 連線建立的開始,到 TCP 連線的斷開,你要傳輸的所有資料的每一個位元組都要編號。這個序號稱為位元組序號。

舉個例子:如果一個 TCP 報文段的序號為 101,它攜帶了 50 位元組的資料,就表示這 50個位元組的資料的位元組序號範圍是 [101, 150],該報文段攜帶的第一個位元組序號是 101,最後一個位元組序號是 150。

(2) 確認號(Acknowledge number)
TCP傳輸的對端通過回覆一個確認號,來表示確認已經接收到了某個 TCP 段。

舉個例子:比如之前傳送方傳送的序號為 101 的 TCP 段,這個段攜帶了 50 位元組資料,則接收方應當回覆的確認號是 151,它表示接收方已經收到了位元組序號為150之前的資料,現在期望你傳送位元組序號為 151 以及以後的資料。

(3)ACK
是一個TCP協議報文中的標誌位元位,如果置1

表示這個報文段是一個回覆確認報文。

注意:為了防止混淆確認號與ACK,一般確認號寫作ack,而ACK就寫為ACK。

(4)FIN
同樣是一個TCP協議報文中的標誌位元位,如果置1表示該報文段用來斷開TCP連線。

介紹完TCP協議報文的一些基本欄位,我們可以來敘述TCP四次揮手的過程了。

TCP四次揮手流程圖

資料傳輸結束後,通訊的雙方都可以釋放連線。現在A和B都處於ESTABLISHED狀態。

(1)第一次揮手

A的應用程式先向其TCP發出連線釋放報文段,並停止傳送資料,主動關閉TCP連線。A把連線釋放報文段首部的FIN置1,其序號seq=x。這時A進入FIN-WAIT-1(終止等待1)

狀態,等待B的確認(請注意:TCP規定,FIN報文段即使不攜帶資料,它也要消耗一個序號)。

(2)第二次揮手

B收到連線釋放報文段後即發出確認,確認號是ack=x+1,序號為seq=y。然後B就進入CLOSE-WAIT(關閉等待)狀態。TCP伺服器程序這時應通知高層程序,因而從A到B這個方向的連線就釋放了,這時的TCP連線處於半關閉狀態,即A已經沒有資料要傳送了,但B若傳送資料,A仍要接收。也就是說,從B到A這個方向的連線並未關閉。這個狀態可能會持續一些時間。

A收到來自B的確認後,就進入FIN-WAIT-2(終止等待2)狀態,等待B發出的連線釋放報文段。

(3)第三次揮手

若B已經沒有要向A傳送的資料,其應用程序就通知TCP釋放連線。這時B發出的連線釋放報文段需要置FIN=1。現假定B的序號為z(在半關閉狀態B可能又傳送了一些資料)。B還必須重複上次已傳送過的確認號ack=x+1。這時B就進入了LAST-ACK(最後確認)狀態,等待A的確認。

(4)第四次揮手

A在收到B的連線釋放報文段後,必須對此發出確認。在確認報文段中把ACK置1確認號ack=z+1,而自己的序號是seq=u+1(根據TCP標準,前面傳送過的FIN報文段要消耗一個序號)。然後進入到TIME-WAIT(時間等待)狀態(請注意:現在TCP連線還沒有釋放掉。必須經過時間等待計時器設定的時間2MSL(MSL:最長報文段壽命)後,A才進入到CLOSED狀態)。

常見面試問題一:為什麼是四次握手,不能是三次握手嗎?

答:與之前需要三次握手的原因類似,如果只是三次揮手,那就相當於伺服器端傳送完第三次揮手的報文後直接進入CLOSED(關閉)狀態,假如此時網路出現問題,丟失了第三次揮手的報文,相當於客戶端沒有收到,那他依舊認為連線沒有結束,在一段時間沒有收到第二次ACK應答報文後,他會重新發送請求斷開連線的報文,但是伺服器端已經關閉,不會再接收報文,又形成了類似死鎖的情況。

常見面試題二:為什麼有CLOSE-WAIT狀態?

答:因為伺服器端收到斷開TCP連線請求時,有可能還有資料沒有向客戶端傳送完畢,需要一段時間來把所有資訊傳輸完畢。

常見面試題三:為什麼有TIME-WAIT狀態?

答:假設客戶端傳送完第四次揮手的報文後,直接進入CLOSED(關閉)狀態。那麼假設此時網路出現問題,報文丟失,那麼因為伺服器端收不到第四次揮手的ACK報文段,所以認為此時TCP連線還沒有斷開。然後重發ACK+FIN報文段,但此時客戶端已經關閉與其的TCP連線,肯定不會再接收該報文,這樣會浪費大量資源。

常見面試題四:什麼情況下會出現大量的TIME-WAIT狀態?該怎麼解決?

答:在高併發且短連線的通訊情況下,伺服器會出現大量TIME-WAIT狀態,這佔用了大量的socket,會影響伺服器的正常通訊服務。

解決方法

  • (1)降低time_wait的時限。
  • (2)設定中允許重用time_wait的socket。
  • (3)設定快速回收time_wait的socket