c++:tcp/ip協議狀態(轉載)

========================================================================================= 
/**
 * 主題:TCP/IP協議的三次握手,四次釋放。
 */

Q1:爲什麼釋放要4步
   因爲tcp/ip是全雙工通訊。在連接的時,syn,ack可以作爲一個包發送。而在釋放的時候fin,ack需要分開發送。

   當主動A關閉連接端,請求關閉時,發送fin.     // 狀態 fin_wait_1      

   被動端B,同意對方的關閉數據傳送請求。發送ACK。  // 狀態 close_wait

   被動端B,把想要發送的數據,此時儘快發送給客戶端。完了之後。

   被動端B,提出自己關閉往對方發送數據的請求。發送fin   // 狀態 last_ack

   主動端A,發送ACK包,同意對方關閉往自己端發送數據的請求。發送ack   // 狀態進入time_wait

02 爲什麼要進入time_wait狀態

   理由是:被動端B發送fin包,關閉自我端數據通訊請求後,進入了last_ack狀態。有可能由於網絡原因,沒有收到主動端A的ack包,此時會進行重發fin包。

   time_wait會持續一段時間(2分鐘)左右,然後雙方進入close狀態。

========================================================================================= 
TCP/IP 連接三次握手與釋放四次握手 


1、建立連接協議(三次握手)
(1)客戶端發送一個帶SYN標誌的TCP報文到服務器。這是三次握手過程中的報文1。 
(2)服務器端迴應客戶端的,這是三次握手中的第2個報文,這個報文同時帶ACK標誌和SYN標誌。因此它表示對剛纔客戶端SYN報文的迴應;同時又標誌SYN給客戶端,詢問客戶端是否準備好進行數據通 訊。

(3)客戶必須再次迴應服務段一個ACK報文,這是報文段32、連接終止協議(四次握手)
    由於TCP連接是全雙工的,因此每個方向都必須單獨進行關閉。這原則是當一方完成它的數據發送任務後就能發送一個FIN來終止這個方向的連接。收到一個 FIN只意味着這一方向上沒有數據流動,一個TCP連接在收到一個FIN後仍能發送數據。首先進行關閉的一方將執行主動關閉,而另一方執行被動關閉。

 (1) TCP客戶端發送一個FIN,用來關閉客戶到服務器的數據傳送(報文段4)。
  (2)服務器收到這個FIN,它發回一個ACK,確認序號爲收到的序號加1(報文段5)。和SYN一樣,一個FIN將佔用一個序號。
  (3)服務器關閉客戶端的連接,發送一個FIN給客戶端(報文段6)。
  (4)客戶段發回ACK報文確認,並將確認序號設置爲收到序號加1(報文段7)。



如果是CLIENT端主動斷掉當前連接的話,那麼雙方關閉這個TCP連接共需要四個packet:

Client ---> FIN ---> Server

Client <--- ACK <--- Server

這時候Client端處於FIN_WAIT_2狀態;而Server 程序處於CLOSE_WAIT狀態。

Client <--- FIN <--- Server

這時Server 發送FIN給Client,Server 就置爲LAST_ACK狀態。

Client ---> ACK ---> Server

Client迴應了ACK,那麼Server 的套接字纔會真正置爲CLOSED狀態。



Server 程序處於CLOSE_WAIT狀態,而不是LAST_ACK狀態,說明還沒有發FIN給Client,那麼可能是在關閉連接之前還有許多數據要發送或者其他事要做,導致沒有發這個FIN packet。

通常來說,一個CLOSE_WAIT會維持至少2個小時的時間。如果有個流氓特地寫了個程序,給你造成一堆的 CLOSE_WAIT,消耗你的資源,那麼通常是等不到釋放那一刻,系統就已經解決崩潰了。



3、 爲什麼建立連接協議是三次握手,而關閉連接卻是四次握手呢?

這是因爲服務端的LISTEN狀態下的SOCKET當收到SYN報文的建連請求後,它可以把ACK和SYN(ACK起應答作用,而SYN起同步作用)放在一個報文裏來發送。但關閉連接時,當收到對方的FIN報文通知時,它僅僅表示對方沒有數據發送給你了;但未必你所有的數據都全部發送給對方了,所以你可以未必會馬上會關閉SOCKET,也即你可能還需要發送一些數據給對方之後,再發送FIN報文給對方來表示你同意現在可以關閉連接了,所以它這裏的ACK報文和FIN報文多數情況下都是分開發送的。

4、 爲什麼TIME_WAIT狀態還需要等2MSL後才能返回到CLOSED狀態?

這是因爲:雖然雙方都同意關閉連接了,而且握手的4個報文也都協調和發送完畢,按理可以直接回到CLOSED狀態(就好比從SYN_SEND狀態到ESTABLISH狀態那樣);但是因爲我們必須要假想網絡是不可靠的,你無法保證你最後發送的ACK報文會一定被對方收到,因此對方處於LAST_ACK狀態下的SOCKET可能會因爲超時未收到ACK報文,而重發FIN報文,所以這個TIME_WAIT狀態的作用就是用來重發可能丟失的ACK報文,並保證於此。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章