1. 程式人生 > 其它 >TCP四次揮手及相關

TCP四次揮手及相關

斷開過程

  1. 假設客戶端準備關閉連線,會發送一個TCP首部FIN置1的報文,即FIN報文給伺服器,然後客戶端進入FIN_WAIT_1狀態;

  2. 服務端收到報文後,會向客戶端傳送一個ACK應答報文,然後服務端進入CLOSED_WAIT狀態;

  3. 客戶端收到來自服務端的ACK報文後,進入FIN_WAIT_2狀態;

  4. 等待伺服器處理完資料後,也向客戶端傳送FIN報文,之後伺服器進入LAST_ACK狀態;

  5. 客戶端收到來自伺服器的FIN報文後,就向伺服器傳送ACK報文,之後進入TIME_WAIT狀態;

  6. 伺服器收到客戶端發來的ACK報文後,進入CLOSED狀態,至此伺服器已完成連線的關閉;

  7. 客戶端在經過2MSL(Maximum Segment Lifetime,報文最大生存時間)的時間後,進入CLOSED狀態,至此客戶端完成連線的斷開。

為什麼是四次揮手?

關閉連線時,客戶端傳送FIN報文,表示其不再發送資料,但還可以接收資料服務端在收到客戶端的FIN報文後,先回一個ACK報文,然後等待完成資料的傳送和處理,再發送FIN報文,所以比三次握手導致多了一次。

四次揮手分別丟失後會發生什麼?

第一次揮手丟失:客戶端傳送FIN報文丟失,遲遲收不到來自伺服器的ACK報文,會觸發超時重傳機制,重新發送FIN報文,超過一定次數客戶端直接進入CLOSED狀態;

第二次揮手丟失:由於ACK報文是不會重傳的,所以如果第二次揮手丟失,客戶端遲遲收不到來自伺服器的ACK報文就會觸發超時重傳機制,重新發送FIN報文,超過一定次數後直接進入CLOSED狀態;

在第二次揮手後,客戶端收到伺服器的ACK報文後,進入FIN_WAIT_2狀態,對於close函式關閉的連線,由於無法再發送和接收資料,這個狀態不能持續太久,一旦超過時長還沒有收到來自伺服器的FIN報文,就會自動進入CLOSED狀態;如果是客戶端使用shutdown函式發起斷開連線,且指定關閉傳送方向,這種情況下客戶端會一直保持FIN_WAIT_2狀態直到第三次揮手。

第三次揮手丟失:伺服器收到客戶端的FIN報文後,核心會自動回覆ACK報文,進入CLOSE_WAIT狀態,呼叫close函式發起關閉連線,核心傳送FIN報文給客戶端,如果這個報文丟失,伺服器遲遲收不到來自客戶端的ACK報文,就會觸發超時重傳機制,伺服器會重發FIN報文,且超過一定次數伺服器自動進入CLOSED狀態;

第四次揮手丟失:客戶端收到FIN報文後,進入TIME_WAIT狀態,並回復ACK報文給伺服器,若該報文丟失,伺服器遲遲沒有收到

ACK報文就會觸發超時重傳機制,重新發送FIN報文,超過次數直接進入CLOSED狀態。

TIME_WAIT等待時間為什麼是2MSL?

網路中可能存在傳送方的資料包,當這些資料包被接收方處理後又會向對方傳送響應,一來一回需要等待2MSL的時間。這個時間是從客戶端接收到伺服器的FIN報文後核心傳送ACK報文開始計時的,如果在這個時間內,客戶端又收到了伺服器重發
的FIN報文,則重新計時。

為什麼需要TIME_WAIT狀態?

為了防止歷史連線中的資料,被後面出現的相同四元組的連線錯誤的接收,(新的連線的ip地址和埠號都相同)2MSL的時長足以保證兩個方向上的資料包都被丟棄,使得原來連線上的資料包在網路中都自然消失,新出現的資料包一定是新連線產生的;保證被動關閉連線(此處是伺服器)的一方,可以正確的關閉連線。如果第四次揮手丟失了,伺服器會重發FIN報文,TIME_WAIT狀態可以保證等待足夠的時間來確保最後的ACK報文能讓伺服器接收。

TIME_WAIT過多有什麼危害?

會佔用記憶體資源,佔用埠資源。如果發起連線一方的TIME_WAIT狀態過多,佔滿了埠資源,會導致無法建立新的連線。