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

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

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

​ 2.服務器端己收到這個數據包以後,知道有客戶端請求鏈接。若是當前有資源,能夠贊成鏈接,則給客戶端發送確認報文。這個確認報文的內容有:SYN=1(沒有變化),seq=y(變成了服務端的序列號),新增ACK=1,ack = x + 1(客戶端序列號+1)。這裏 SYN=1,因此報文不能攜帶數據,一樣消耗了服務端的一個序列號。而後服務端進入了 SYN-RCVD(同步收到)狀態。blog

3.客戶端收到服務端的確認報文以後,還須要給客戶端發送一個客戶端的確認報文。這個報文的內容是 ACK = 1,seq = x + 1,ack = y + 1。這裏沒有了 SYN 這個字段,因此這個報文能夠攜帶數據。這個客戶端確認報文發送出去以後,客戶端進入ESTABLISHED(已創建鏈接)狀態。服務端接收到這個數據包以後,也進入了 ESTABLISHED(已創建鏈接)狀態。three

上面給出的鏈接創建過程叫作 三次握手(three-way handshake)進程

提問: 正常來講,鏈接的創建只須要前面兩次就足夠了,爲何還要有一次客戶端給服務器端的 ACK ?圖片

1)這是由於,首先創建鏈接,必需要有兩次握手吧,客戶端主動一次,告知服務端,我想和你創建鏈接,而後看服務端是否贊成。而後若是服務端贊成的話,得給一個回覆,而後開始等待客戶端的數據包,這就是兩次握手。若是這個時候就創建鏈接,客戶端開始給服務端發送數據包,在正常狀況下沒啥問題。可是因爲網絡並非100%任什麼時候候都穩定,一旦由於某些緣由致使服務端發送給客戶端的確認報文丟失,那這個時候客戶端收不到確認數據包,會誤覺得服務端不一樣意鏈接,不會給服務端發送數據包,可是這時候服務端已經在等待了。這樣的差錯會致使服務端一直處於等待狀態,浪費資源。

​ 2) 而三次握手的話,客戶端在確認服務端贊成以後再發一次數據包給服務端,告知服務端,無論怎麼樣我都會給你發送數據包的。由於TCP協議中,創建鏈接以後,每一次發送數據包客戶端都會等待服務端的確認信息,若是收不到某一個數據包的確認信息,客戶端就會重發這個數據包。這樣就不會發生差錯了。

TCP的鏈接釋放

前面說了TCP的鏈接創建過程是三次握手,如今咱們來講釋放過程,也就是咱們常說的四次揮手。

話很少說,上圖:

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

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

​二、服務端接收到釋放數據包以後發出確認,確認包中內容:確認號ack=u+1,序列號seq=v(這個v是服務端上一個發送的數據包的序列號+1),另外一個是ACK=1。而後服務端進入CLOSE-WAIT(關閉等待)。這個時候客戶端到服務端的鏈接已經結束了。可是TCP是全雙工通訊,由於這個時候是客戶端主動發起的結束,在服務端這邊可能還存在着數據沒有徹底發送給客戶端,因此服務端到客戶端仍然沒有結束。客戶端已經不能在發送數據了,若是服務端還有數據發送過來,客戶端仍然要接收。

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

四、客戶端收到服務端的鏈接釋放數據包以後,發出一個確認數據包,內容: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次握手,也能夠叫作四次揮手。

好了,今天咱們就聊到這裏,你們下期見。

相關文章
相關標籤/搜索