TCP連接的建立與釋放(超詳細)


前言:在計算機網絡協議中,TCP只是其中一個,然而在網絡使用中,TCP也是最離不開的協議之一,它的重要性毋庸置疑,最最重要的是,面試的重點就是它啊,嗚嗚~~,今天我們一起來看下TCP的連接建立與釋放,相信很多小伙伴也想給他一次性整明白。

TCP連接的建立

下圖給出TCP三次握手的過程:
在這里插入圖片描述

在進入正文之前先讓我們來復習復習幾個選項位,待會兒會用到哦!!!

  1. 確認ACK
    僅當ACK = 1 時確認號字段才有效。當ACK = 0 時,確認號無效。TCP規定:在連接建立后,所有傳送的報文段都必須把ACK置為1。
  2. 同步SYN
    在連接建立時用來同步序號。當 SYN = 1 而 ACK = 0 時,表名這是一個連接請求報文段。對方若同意建立連接,則應在響應的報文段中使 SYN = 1 和 ACK = 1 。
  3. 終止FIN
    用來釋放一個連接。當FIN = 1 時,表示此報文段的發送方的數據已經發送完畢,並要求釋放運輸連接。

在復習完這些選項之后,我們一起來聊聊TCP連接的建立:

​ 如上圖畫出了TCP的建立連接過程。假定主機A運行的時TCP客戶端,而B運行TCP服務器程序。途中主機下面的方框分別是TCP進程所處的狀態。請注意,此時A是主動打開連接,B是被動打開連接。

​ 1. 初始時候,客戶端和服務端都處於 CLOSED (關閉) 狀態。當客戶端需要給服務端發送數據包的時候,客戶端主動打開連接。這個時候應該是通知了服務端,讓服務端也打開連接,所以服務端是被動打開連接。打開連接之后,分別開始創建傳輸控制模塊 TCB,接着服務端進入 LISTEN(監聽)狀態,等待客戶端的連接請求。客戶端也開始准備連接請求數據包,開始發送。客戶端發送的第一個數據包是一個連接請求報文段,這個報文的內容如上圖,是一個同步位SYN = 1,另一個是一個初始序號 seq = x 。TCP 規定,SYN = 1 的報文段不能攜帶數據,但要消耗一個序列號。客戶端發送了這個報文之后,進入SYN-SENT(同步已發送)狀態。

​ 2.服務器端己收到這個數據包之后,知道有客戶端請求連接。如果當前有資源,可以同意連接,則給客戶端發送確認報文。這個確認報文的內容有:SYN=1(沒有變化),seq=y(變成了服務端的序列號),新增ACK=1,ack = x + 1(客戶端序列號+1)。這里 SYN=1,所以報文不能攜帶數據,同樣消耗了服務端的一個序列號。然后服務端進入了 SYN-RCVD(同步收到)狀態。

3.客戶端收到服務端的確認報文之后,還需要給客戶端發送一個客戶端的確認報文。這個報文的內容是 ACK = 1,seq = x + 1,ack = y + 1。這里沒有了 SYN 這個字段,所以這個報文可以攜帶數據。這個客戶端確認報文發送出去之后,客戶端進入ESTABLISHED(已建立連接)狀態。服務端接收到這個數據包之后,也進入了 ESTABLISHED(已建立連接)狀態。

上面給出的連接建立過程叫做 三次握手(three-way handshake)

提問: 正常來說,連接的建立只需要前面兩次就足夠了,為什么還要有一次客戶端給服務器端的 ACK ?

1)這是因為,首先建立連接,必須要有兩次握手吧,客戶端主動一次,告知服務端,我想和你建立連接,然后看服務端是否同意。然后如果服務端同意的話,得給一個回復,然后開始等待客戶端的數據包,這就是兩次握手。如果這個時候就建立連接,客戶端開始給服務端發送數據包,在正常情況下沒啥問題。但是由於網絡並不是100%任何時候都穩定,一旦因為某些原因導致服務端發送給客戶端的確認報文丟失,那這個時候客戶端收不到確認數據包,會誤以為服務端不同意連接,不會給服務端發送數據包,但是這時候服務端已經在等待了。這樣的差錯會導致服務端一直處於等待狀態,浪費資源。

​ 2) 而三次握手的話,客戶端在確認服務端同意之后再發一次數據包給服務端,告知服務端,不管怎么樣我都會給你發送數據包的。因為TCP協議中,建立連接之后,每一次發送數據包客戶端都會等待服務端的確認信息,如果收不到某一個數據包的確認信息,客戶端就會重發這個數據包。這樣就不會發生差錯了。

TCP的連接釋放

前面說了TCP的連接建立過程是三次握手,現在我們來說釋放過程,也就是我們常說的四次揮手。

話不多說,上圖:

在這里插入圖片描述
如上圖所示,我們來詳細說一下TCP的釋放過程:

1、當TCP連接需要釋放時,客戶端和服務端都是處於 ESTABLISHED(已建立連接 ) 狀態。此時,客戶端數據發送完畢,想要結束連接了,主動發出連接釋放請求數據包。這個數據包內容:Fin=1,seq=u(這個u是這個數據包之前一個數據包的序列號+1),客戶端進入FIN-WAIT-1(終止等待1)狀態,不在發送數據包,等待服務端的確認。

​2、服務端接收到釋放數據包之后發出確認,確認包中內容:確認號ack=u+1,序列號seq=v(這個v是服務端上一個發送的數據包的序列號+1),另一個是ACK=1。然后服務端進入CLOSE-WAIT(關閉等待)。這個時候客戶端到服務端的連接已經結束了。但是TCP是全雙工通信,因為這個時候是客戶端主動發起的結束,在服務端這邊可能還存在着數據沒有完全發送給客戶端,所以服務端到客戶端仍然沒有結束。客戶端已經不能在發送數據了,如果服務端還有數據發送過來,客戶端仍然要接收。

3、客戶端收到服務端的確認之后,進入FIN-2(終止等待2)狀態,等待服務端發送服務端發器的連接釋放數據包。這時候服務端可能還有一些數據包要發送給客戶端,客戶端一一接收。最后,沒有數據要發送了之后,服務端發送連接釋放數據包,這個數據包內容:FIN=1,ACK=1,seq=w(因為在服務端回復客戶端的連接請求(數據包的序列號是v)之后,可能仍然有其他數據包要發送,所以這里的w不一定是v+1),ack=u+1(確認號和上次回復客戶端的請求釋放連接的確認號一樣)。接着服務端進入LAST-ACK(最后確認狀態),等待客戶端的確認。

4、客戶端收到服務端的連接釋放數據包之后,發出一個確認數據包,內容:ACK=1,seq=u+1,ack = w+1。然后客戶端進入TIME-WAIT(時間等待)狀態。這個時候TCP還沒有釋放。仍需要經過時間等待計時器設置的時間2MSL后,客戶端才會進入CLOSED狀態。MSL稱為最長報文段壽命。RFC793建議把這個值設為2分鍾,那這樣的話,在客戶端收到服務端的連接釋放數據包之后,需要等待4分鍾才能進入CLOSED狀態。這顯然時間太長了,不過這個值設為2分鍾也只是建議,還是可以設置適合的時間的。最后服務端收到這個客戶端的確認包之后就進入了CLOSED狀態。顯然,服務端一般先於客戶端進入關閉狀態。

​客戶端需要等待 2MSL 時間才完全結束TCP連接的原因:

1)為了保證客戶端發送的最后一個確認包能正確到達服務端。因為如果由於網絡原因丟失的話,服務端會重新發送連接釋放數據包,在等待過程中,如果真的發生這種情況就可以得到處理。客戶端每接收到一次服務端發送來的接釋放數據包都會重新設置時間等待計時器,然后等待2MSL時間才完全結束TCP連接。
2)等待才2MSL時間完全結束TCP連接,可以避免再次開啟TCP連接的時候收到上一次TCP連接存在網絡中的數據包,顯然這樣的數據包不是屬於本次連接的,是無效的數據包。

以上就是TCP連接釋放的4次握手,也可以叫做四次揮手。

好了,今天我們就聊到這里,大家下期見。


免責聲明!

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



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