純給自己看的
發起關閉的一方是客戶端,被動關閉的一方是伺服器。
(1)客戶端a傳送乙個fin=1,用來關閉客戶a到伺服器b的資料傳送。 (圖上畫的對,還有乙個seq=n)
(2)伺服器b收到這個fin,它發回乙個ack=1,確認序號ack為收到的序號加1。
(3)伺服器b關閉與客戶端a的連線,傳送乙個fin=1給客戶端a。 (圖上畫的對,還有乙個seq=m,ack=n+1,ack=1)
(4)客戶端a發回ack=1報文確認,並將確認序號ack設定為收到序號加1(也就是m+1)。
伺服器收到fin但是還沒發出ack的狀態是close_wait。
客戶端發出ack報文確認的時候進入time_wait狀態,
等待2msl時間,為了保證這個ack報文沒有丟失,如果丟失,伺服器沒有接收到報文,就會超時重傳第三步的報文。
那四次分手又是為何呢?tcp協議是一種面向連線的、可靠的、基於位元組流的運輸層通訊協議。tcp是全雙工模式,這就意味著,當主機1發出fin
報文段時,只是表示主機1已經沒有資料要傳送了,主機1告訴主機2,它的資料已經全部傳送完畢了;但是,這個時候主機1還是可以接受來自主機2的資料;當主機2返回ack
報文段時,表示它已經知道主機1沒有資料傳送了,但是主機2還是可以傳送資料到主機1的;當主機2也傳送了fin
報文段時,這個時候就表示主機2也沒有資料要傳送了,就會告訴主機1,我也沒有資料要傳送了,之後彼此就會愉快的中斷這次tcp連線。如果要正確的理解四次分手的原理,就需要了解四次分手過程中的狀態變化。
time_wait
time_wait 是主動關閉鏈結時形成的,等待2msl時間,約4分鐘。
主要是防止最後乙個ack丟失。 由於time_wait 的時間會非常長,因此server端應儘量減少主動關閉連線
close_wait
close_wait是被動關閉連線是形成的。根據tcp狀態機,伺服器端收到客戶端傳送的fin,則按照tcp實現傳送ack,因此進入close_wait狀態。但如果伺服器端不執行close(),就不能由close_wait遷移到last_ack,則系統中會存在很多close_wait狀態的連線。此時,可能是系統忙於處理讀、寫操作,而未將已收到fin的連線,進行close。此時,recv/read已收到fin的連線socket,會返回0。
為什麼需要 time_wait 狀態?
假設最終的ack丟失,server將重發fin,client必須維護tcp狀態資訊以便可以重發最終的ack,否則會傳送rst,結果server認為發生錯誤。tcp實現必須可靠地終止連線的兩個方向(全雙工關閉),client必須進入 time_wait 狀態,因為client可能面 臨重發最終ack的情形。
為什麼 time_wait 狀態需要保持 2msl 這麼長的時間?
如果 time_wait 狀態保持時間不足夠長(比如小於2msl),第乙個連線就正常終止了。第二個擁有相同相關五元組的連線出現,而第乙個連線的重複報文到達,干擾了第二個連線。tcp實現必須防止某個連線的重複報文在連線終止後出現,所以讓time_wait狀態保持時間足夠長(2msl),連線相應方向上的tcp報文要麼完全響應完畢,要麼被 丟棄。建立第二個連線的時候,不會混淆。
tcp 四次揮手 TCP四次揮手
tcp斷開連線的過程 客戶端傳送fin報文,表明客戶端將不在傳送資料。具體過程 把fin標誌位改為1,序號seq u,之前傳送的資料加1,這裡規定即使不攜帶資料序號也要 1。該過程中客戶端通過close系統呼叫從established狀態進入fin wait 1狀態。第二次揮手 服務端收到客戶端發來...
TCP四次揮手
四次揮手 1.客戶端程序發出連線釋放報文,並且停止傳送資料。釋放資料報文首部,fin 1,其序列號為seq u 等於前面已經傳送過來的資料的最後乙個位元組的序號加1 此時,客戶端進入fin wait 1 終止等待1 狀態。tcp規定,fin報文段即使不攜帶資料,也要消耗乙個序號。2.伺服器收到連線釋...
TCP四次揮手
之前分析了tcp的在客戶端和服務端建立連線時的三次握手,那麼順便也學習下tcp的四次揮手吧!我們就直接開始分析通訊過程吧!第一次揮手 當客戶端已經不需要向服務端傳送資料時 即請求斷開連線 客戶端先傳送乙個fin fin 1,seq u 給服務端,來告訴服務端它已經完成了想要的通訊,並請求斷開連線,此...