tcp在TIME WAIT狀態下等待2MSL

2021-07-31 06:32:12 字數 3288 閱讀 6878

第一,為了保證a傳送的最後乙個ack報文能夠到達b。這個ack報文段有可能丟失,因而使處在last-ack狀態的b收不到對已傳送的fin+ack報文段的確認。b會超時重傳這個fin+ack報文段,而a就能在2msl時間內收到這個重傳的fin+ack報文段。如果a在time-wait狀態不等待一段時間,而是在傳送完ack報文段後就立即釋放連線,就無法收到b重傳的fin+ack報文段,因而也不會再傳送一次確認報文段。這樣,b就無法按照正常的步驟進入closed狀態。 

第二,a在傳送完ack報文段後,再經過2msl時間,就可以使本連線持續的時間所產生的所有報文段都從網路中消失。這樣就可以使下乙個新的連線中不會出現這種舊的連線請求的報文段。 

1 tcp關閉時的四次握手

tcp連線在關閉的的時候,執行的是乙個四次握手的過程,下圖是客戶端發起的關閉時客戶端和伺服器的狀態轉換圖

具體過程如下:

1、 客戶端傳送fin報文段,進入fin_wait_1狀態。

2、 伺服器端收到fin報文段,傳送ack表示確認,進入close_wait狀態。

3、 客戶端收到fin的確認報文段,進入fin_wait_2狀態。

4、 伺服器端傳送fin報文端,進入last_ack狀態。

5、 客戶端收到fin報文端,傳送fin的ack,同時進入time_wait狀態,啟動time_wait定時器,超時時間設為2msl。

6、 伺服器端收到fin的ack,進入closed狀態。

7、 客戶端在2msl時間內沒收到對端的任何響應,time_wait超時,進入closed狀態。

client在發出server 端fin的ack以後,進入了time_wait的狀態,知道2msl以後,才會關閉。先來解釋下2msl,max segment lifetime,最大生成時間。msl的值在一般的實現中取30s,有些實現採用2分鐘。在tcp的狀態機中的「被動關閉」,從close_wait到 last_ack中有乙個如下的規則:當t c p執行乙個主動關閉,並發回最後乙個a ck,該連線必須在time_wait狀態停留的時間為2倍的msl。這樣可讓tcp再次傳送最後的ack以防這個ack丟失。個規則導致乙個後果就是在 這個2msl的時間內,該位址上的鏈結(客戶端位址、埠和伺服器端的位址、埠)不能被使用。比如我們在建立乙個鏈結後關閉鏈結然後迅速重啟鏈結,那麼 就會出現埠不可用的情況。

2 time_wait狀態的必要性

如果不考慮報文延遲、丟失,確認延遲、丟失等情況,time_wait的確沒有存在的必要。當網路在不理想的情況下通常會有報文的丟失延遲發生,讓我們看下面的乙個特例:

客戶端進入傳送收到四次握手關閉的最後乙個ack後,進入time_wait同時傳送ack,如果其不停留2msl時間,而是馬上關閉連線,銷毀連線上的資源,當傳送如下情況時,將不能正常的完成四次握手關閉:

客戶端傳送的ack在網路上丟失,這樣伺服器端收不到最後的ack,重傳定時器超時,將重傳fin到客戶端,由於客戶端關於該連線的所有資源都釋放,收到重傳的fin後,它沒有關於這個fin的任何資訊,所以向伺服器端傳送乙個rst報文端,伺服器端收到rst後,認為搞連線出現了異常(而非正常關閉)。

所以,在time_wait狀態下等待2msl時間端,是為了能夠正確處理第乙個ack(最長生存時間為msl)丟失的情況下,能夠收到對端重傳的fin(最長生存時間為msl),然後重傳ack。

是否只要主動關閉方在time_wait狀態下停留2msl,四次握手關閉就一定正常完成呢?

答案是否定的?可以考慮如下的情況,

time_wait狀態下傳送的ack丟失,last_ack時刻設定的重傳定時器超時,傳送重傳的fin,很不幸,這個fin也丟失,主動關閉方在time_wait狀態等待2msl沒收到任何報文段,進入closed狀態,當此時被動關閉方並沒有收到最後的ack。所以即使要主動關閉方在time_wait狀態下停留2msl,也不一定表示四次握手關閉就一定正常完成。

結論:在time_wait下等待2msl,只是為了盡最大努力保證四次握手正常關閉。確保老的報文段在網路中消失,不會影響新建立的連線

考慮如下的情況,主動關閉方在time_wait狀態下傳送的ack由於網路延遲的原因沒有按時到底(但並沒有超過msl的時間),導致被動關閉方重傳fin,在fin重傳後,延遲的ack到達,被動關閉方進入closed狀態,如果主動關閉方在time_wait狀態下傳送ack後馬上進入closed狀態(也就是沒有等待)2msl時間,則上述的連線已不存在:現在考慮下面的情況,假設上述的鏈結的四元組為(192.201.0.80:23,192.201.0.85:5555),由於連線已關閉,我們可以馬上建立乙個新的連線,並且這個連線的四元組也是(192.201.0.80:23,192.201.0.85:5555),那麼當上乙個連線的重傳fin到達主動關閉方時,被新的連線所接受,這將導致新的連線被復位,很顯然,這不是我們希望看到的事情。

新的連線要建立,必須是在主動關閉方和被動關閉方都進入到closed狀態之後才有可能。所以,最有可能導致舊的報文段影響新的連線的情況是:

在time_wait狀態之前,主動關閉方傳送的報文端在網路中延遲,但是time_wait設定為2msl時,這些報文端必然會在網路中消失(最大生存時間為msl)。被動關閉方最有可能影響新連線的報文段就是我們上面討論的情況,對方ack延遲到達,在此之前重傳的fin,這個報文端傳送之後,time_wait的定時器超時時間肯定大於msl,在1msl時間內,這個fin要麼在網路中因為生成時間到達而消失,要麼到達主動關閉方被這確的處理,不會影響新建立的連線。

什麼是2msl

msl是maximum segment lifetime英文的縮寫,中文可以譯為「報文最大生存時間」,他是任何報文在網路上存在的最長時間,超過這個時間報文將被丟棄。因為tcp報文(segment)是ip資料報(datagram)的資料部分,具體稱謂請參見《資料在網路各層中的稱呼》一文,而ip頭中有乙個ttl域,ttl是time to live的縮寫,中文可以譯為「生存時間」,這個生存時間是由源主機設定初始值但不是存的具體時間,而是儲存了乙個ip資料報可以經過的最大路由數,每經過乙個處理他的路由器此值就減1,當此值為0則資料報將被丟棄,同時傳送icmp報文通知源主機。rfc 793中規定msl為2分鐘,實際應用中常用的是30秒,1分鐘和2分鐘等。

2msl即兩倍的msl,tcp的time_wait狀態也稱為2msl等待狀態,當tcp的一端發起主動關閉,在發出最後乙個ack包後,即第3次握手完成後傳送了第四次握手的ack包後就進入了time_wait狀態,必須在此狀態上停留兩倍的msl時間,等待2msl時間主要目的是怕最後乙個ack包對方沒收到,那麼對方在超時後將重發第三次握手的fin包,主動關閉端接到重發的fin包後可以再發乙個ack應答包。在time_wait狀態時兩端的埠不能使用,要等到2msl時間結束才可繼續使用。當連線處於2msl等待階段時任何遲到的報文段都將被丟棄。不過在實際應用中可以通過設定so_reuseaddr選項達到不必等待2msl時間結束再使用此埠。

TCP連線的TIME WAIT狀態

time wait狀態是tcp的11個狀態其中之一,是發生在正常關閉tcp連線的時候發生的。如下圖所示 在這幅圖中我們可以明顯看出,流程是這樣的,顯示主動傳送乙個fin報文,然後接收到乙個ack報文,這樣這一方的連線已經關閉,也就是不能再傳送資料了,進入fin wait2狀態,這個狀態就是為了等待,...

TCP中的time wait狀態

tcp連線的建立三次握手,連線的斷開需要四次揮手。tcp連線在四次揮手的過程中,主動關閉的一端往往會進入乙個叫time wait的狀態。這個狀態是被動關閉端發出fin分節以後,被動端就會進入last ack狀態,主動關閉端接受到這個fin分節以後就會發出最後乙個ack分節,並進入time wait狀...

TCP中的TIME WAIT狀態

上面是tcp客戶端向伺服器申請鏈結 傳輸資料 斷開連線的過程。在斷開連線的4次握手過程中,執行主動關閉的那一端 也就是我們這個圖中的客戶端 將進入time wait狀態 這個狀態將持續2msl的時間 最長分節生命週期 maximun segment lifetime 每乙個tcp都有乙個msl的值 ...