四次揮手都做什麼?
TCP的連接是全雙工的,所以連接的拆除需要單獨將兩個通道分別拆除,而四次揮手所做的事情就是拆除兩條通道和釋放資源。
TCP 提供了連接的一端結束他的發送後,還能接收來自另一端數據的能力,也就是所謂的半關閉。
這裏以Client作爲主動發起端,Server作爲被動關閉端。
第一步,Client主動發起一個Req給Server,裏面包含FIN標識位=1,CLient的Seq序列號N,表示的是當前Client在該連接上的當前序列號。
第二步,Server端在收到這個含有FIN的Req消息之後,校驗無誤之後會立馬回覆ACK消息給CLient端,消息內部包含ACK標誌位爲1,同時Seq號碼是FIN的請求消息的Seq號+1。此時的Sever同時會主動發個結束標識給Server上面的應用層程序,應用層程序可以決定是立馬結束,還是等到服務其上面的該連接中的數據處理完了之後,在發送FIN消息給Client來關掉另外的一半連接。
第三步,Server端在處理完該連接上面的Pending住的數據之後,應用程序會close這個連接。Client會主動發起FIN的Req消息給Client端。消息內部帶有,FIN=1的結束符標識位,以及Server端的Seq序列號。
第四步,Client端在收到對應的FIN消息之後,會主動通知應用層程序,告知這個連接現在需要關閉了。然後,Client會回覆ACK消息給Server,以便斷開另外一個方向的通道,這個消息包含ACK=1的標識位和FIN的REQ帶過來的Seq+1。
爲什麼需要四次揮手?
因爲TCP是一個全雙工協議,必須單獨拆除每一條信道。4次揮手的目的是終止數據傳輸,並回收資源,此時兩個端點兩個方向的序列號已經沒有了任何關係,必須等待兩方向都沒有數據傳輸時才能拆除虛鏈路,不像初始化時那麼簡單,發現SYN標誌就初始化一個序列號並確認SYN的序列號。因此必須單獨分別在一個方向上終止該方向的數據傳輸。
如果是三次揮手,會怎麼樣?三次的話,被動關閉端在收到FIN消息之後,需要同時回覆ACK和Server端的FIN消息。如果Server端在該連接上面並沒有Pending的消息要處理,那麼是可以的,如果Server端還需要等待一段時間纔可以關閉另外一個方向的連接,那麼這樣的三次揮手就不能滿足條件。
四次揮手的狀態轉換?
Client端:
ESTABLISHED---發送FIN給Server-->FIN_WAIT_1---接收到Server端的FIN對應的ACK-->FIN_WAIT_2---收到Server端發送過來的FIN消息-->FIIN_WAIT--2MSL之後會進入-->CLOSED
Server端:
ESTABLISHED---接收到Client端的FIN->CLOSED_WAIT--Server端的應用程序關閉發送FIN--> LAST_ACK---收到Client對於FIN的ACK響應-->FIIN_WAIT---->CLOSED
其中四次揮手與Scoket函數的對應關係如下所示:
四次揮手失敗了會怎麼樣?
四次揮手裏面,最經典的場景,是Client處於TIME_WAIT之後的2MSL的時間處理。(備註:MSL是TCP報文裏面最大生存時間,它是任何報文段被丟棄前在網絡內的最長時間。)
設置2MSL的目的是爲了處理,Server端在重傳最後一個FIN的時候,Client能夠發送最後一個ACK的時間。
這個時間段內,不管是Client端還是Server端,最好都不要重用這個TCP的端口,否則的話,可能會導致根據這個端口新建立的連接被錯誤的關掉,詳細情況如下所示:
step1:Server發送給Client的最後一個FIN,Client收到了,也發了ACK給Server,但是Server並沒有收到這個ACK。step2:於是CLient複用了這個Port號,於是新建了一條連接,這裏假設叫newConnection。step3:Server在此過程中已經發送了重傳的FIN給Client,Client上面剛建立完成的newConnection就會再次被關掉。
參考資料:
https://blog.csdn.net/qq_34501940/article/details/51119726
https://blog.csdn.net/varyall/article/details/80348850
TCP/IP詳解 卷1
灰子做於二零一九年一月二十一日。
【原創作品,歡迎分享,請勿轉載,謝謝尊重!!】