計算機網絡基礎:TCP協議之握手與揮手

上一篇裏,我們瞭解了傳輸層的TCP協議以及TCP協議實現的機制,接下來我們就來詳解一下TCP協議的連接管理機制:

連接管理

         TCP提供面向有連接的數據傳輸,面向有連接是指在數據通信開始之前先做好通信兩端之間的準備工作。

         也就是說TCP協議需要在客戶端與服務器成功連接之後纔可使用,那麼客戶端與服務器的連接過程是什麼呢?

  • TCP建立連接:三次揮手 (客戶端連接服務器需要完成三次握手
  • TCP斷開連接:四次揮手 (通信完畢過後斷開連接需要四次揮手

       

三次握手

  • 客戶端與服務器在握手之前都做了一些前期的準備。服務器在開始先分配一個描述符,然後填充一下sockaddr_in結構體,綁定創建的文件描述符及服務器端口,接着listen監聽,使得剛纔的文件描述符成爲一個監聽描述符,最後阻塞至accept等待客戶端的連接。而客戶端相較來說簡單一些,就是分配文件描述符,填充sockaddr_in結構體,最後進行connect請求服務器的連接,直至服務器響應。
  • 在客戶端經過connect請求服務器響應的時候,向服務器發送同步報文段也就是SYN請求,發送完畢後等待服務器響應。服務器如果收到了SYN同步報文段,那麼就會給客戶端發送ACK響應,意爲收到了客戶端發送的同步報文段,在此同時,服務器也會發送SYN同步報文段,請求客戶端的響應。客戶端在接收到SYN同步報文段後也會發送ACK響應來回復服務器。這個過程就是三次握手的過程
  • 這樣看來,客戶端與服務器的連接是雙方的,兩者都得發送請求同樣兩者也都得響應。圖上來看,SYN_SENT就是請求連接狀態,SYN_RCVD就是等待連接狀態。在三次握手成功後,服務器與客戶端都會進入ESTABLISHED狀態,也就是TCP連接成功態,這個時候就可以進行數據的傳送了。
  • 這個過程中如果客戶端的SYN請求如果丟包,服務器不會響應,而客戶端會有一個等待時間,等待時間到達,未收到ACK響應,這個時候客戶端會發起再次請求。如果多次請求都未成功,此時客戶端可能會判斷網絡異常,不會再次請求。同樣再服務器接收到客戶端的SYN請求之後也會發送ACK響應同時發送SYN請求。如果客戶端遲遲不給服務器ACK響應,服務器也會進行重發,直至判斷網絡異常。所以說,三次握手任意一個缺失都不會連接成功,也就無法通信。所以三次握手也是確保TCP可靠的一種方式。

 

四次揮手

         在客戶端與服務器通信完畢後,客戶端調用close,開始進行四次揮手:

  • 在客戶端與服務器數據傳輸完畢之後,客戶端沒有請求了,所以此時調用close關閉文件描述符,開始進入FIN_WAIT_1狀態,同時向服務器發送FIN結束報文段並等待服務器的響應。當服務器這裏收到了FIN結束報文段時,這個時候服務器進入CLOSE_WAIT狀態。並給客戶端進行應答發送ACK。當客戶端收到服務器的ACK響應時,進入FIN_WAIT_2狀態。當服務器調用close時,會向客戶端發送FIN結束報文段。此時進入LAST_ACK狀態。此時的客戶端收到服務器發送的FIN時,會向服務器進行響應ACK,並且客戶端進入TIME_WAIT狀態,TIME_WAIT結束之後,進入CLOSED,斷開連接成功。當服務器收到客戶端最後的ACK時,進入CLOSED狀態,斷開連接成功。
     

一、CLOSE_WAIT與LAST_ACK狀態:

1、在三次握手的時候服務器可以將SYN與ACK同時發送,但是爲什麼這裏服務器發送的FIN與ACK是分開發送的呢?

  • 首先FIN信號是由於調用close所以才發送的。而客戶端調用close時,發送FIN結束報文段並進入FIN_WAIT_1狀態。而這個報文段在服務器中用戶態其實是無法感知的,內核會自己處理這個報文段,也就是說由內核進行ACK響應。這個過程中不是由用戶代碼決定的,服務器的FIN是由用戶代碼調用close發送的,所以內核與服務器不一定是同時處理這個信息的。所以FIN與ACK不一定是同時發送出去的。(注意:這裏是不一定!!!但是三次握手的時候發送SYN是由內核直接完成的,所以這就可以達到一個同步發送的情況。)

2、若服務器的代碼沒有調用close,意味着並沒有發送FIN結束報文段。那麼此連接的服務器將會長期保持在CLOSE_WAIT狀態,這會有什麼影響? 

  • 服務器長期保持在CLOSE_WAIT狀態,也就是說分配的文件描述符並沒有關閉並歸還。那麼大量的CLOSE_WAIT存在的話,就會導致一種資源的泄漏可能到最後就沒有可分配的文件描述符了,那麼就會使一些客戶端無法連接,從而造成不可估量的影響。

二、TIME_WAIT狀態

1、在客戶端最後一次發送ACK響應後,進入TIME_WAIT狀態,而這個狀態的時候客戶端在做什麼呢? 

  • 此時客戶端在等待!在客戶端最後發送ACK響應後,進入TIME_WAIT狀態,這是爲了防止最後發送的ACK響應丟包。在這裏,TIME_WAIT狀態會等待2MSL的時間。
  • MSL(Max Segment Life):報文的最大生存時間,這裏的生存時間指的是一個報文從發生到被接收到的整個過程,這個過程的時間就是MSL。(Linux下可以利用cat /proc/sys/net/ipv4/tcp_fin_timeout來查看MSL的值) 

2、客戶端最後一次發送ACK響應後,爲什麼要等待2MSL呢?

  • 爲了確保最後一條ACK消息的到達。因爲客戶端在發送最後一條ACK響應後進入TIME_WAIT狀態,如果這條ACK報文丟失,那麼服務器在等待一個MSL的時間過後發現沒有收到ACK響應,那麼它會重新發送一條FIN報文。這樣一條ACK響應的時間加上重發的FIN的時間正好就是2MSL。如果客戶端等待2MSL後沒有收到FIN報文,那麼意味着服務器收到了客戶端發送的ACK報文,這樣就斷開連接。 

3、在TIME_WAIT的時候,客戶端與服務器之間的TCP連接還是存在的。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章