TIME_WAIT狀態
TCP要保證在所有可能的情況下使得所有的資料都能夠正確被投遞。
當關閉一個 socket 連線時,主動關閉一端的 socket 將進入TIME_WAIT狀態,而被動關閉一方則轉入CLOSED狀態。
見圖解。
當一個socket關閉的時候,是透過兩端互發資訊的四次握手過程完成的,當一端呼叫close()時,就說明本端沒有資料再要傳送了。這好似看來在握手完成以後,socket就都應該處於關閉CLOSED狀態了。但這有兩個問題,
第一:我們沒有任何機制保證最後的一個ACK能夠正常送達
第二:網路上仍然有可能有殘餘的資料包(wandering duplicates,或老的重複資料包),我們也必須能夠正常處理。
假設最後一個ACK丟失了,伺服器會重發它傳送的最後一個FIN,所以客戶端必須維持一個狀態資訊,以便能夠重發ACK;如果不維持這種狀態,客戶端在接收到FIN後將會響應一個RST,伺服器端接收到RST後會認為這是一個錯誤。如果TCP協議能夠正常完成必要的操作而終止雙方的資料流傳輸,就必須完全正確的傳輸四次握手的四個節,不能有任何的丟失。這就是為什麼socket在關閉後,仍然處於 TIME_WAIT狀態,因為他要等待以便重發ACK。
如果目前連線的通訊雙方都已經呼叫了close(),假定雙方都到達CLOSED狀態,而沒有TIME_WAIT狀態時,就會出現如下的情況。現在有一個新的連線被建立起來,使用的IP地址與埠與先前的完全相同,後建立的連線又稱作是原先連線的一個化身。還假定原先的連線中有資料報殘存於網路之中,這樣新的連線收到的資料報中有可能是先前連線的資料報。為了防止這一點,TCP不允許從處於TIME_WAIT狀態的socket建立一個連線。處於TIME_WAIT狀態的socket在等待兩倍的MSL時間以後(之所以是兩倍的MSL,是由於MSL是一個數據報在網路中單向發出到認定丟失的時間,一個數據報有可能在傳送圖中或是其響應過程中成為殘餘資料報,確認一個數據報及其響應的丟棄的需要兩倍的MSL),將會轉變為CLOSED狀態。這就意味著,一個成功建立的連線,必然使得先前網路中殘餘的資料報都丟失了。
由於TIME_WAIT狀態所帶來的相關問題,我們可以透過設定SO_LINGER標誌來避免socket進入TIME_WAIT狀態,這可以透過傳送RST而取代正常的TCP四次握手的終止方式。但這並不是一個很好的主意,TIME_WAIT對於我們來說往往是有利的。
TIME_WAIT狀態
TCP要保證在所有可能的情況下使得所有的資料都能夠正確被投遞。
當關閉一個 socket 連線時,主動關閉一端的 socket 將進入TIME_WAIT狀態,而被動關閉一方則轉入CLOSED狀態。
見圖解。
當一個socket關閉的時候,是透過兩端互發資訊的四次握手過程完成的,當一端呼叫close()時,就說明本端沒有資料再要傳送了。這好似看來在握手完成以後,socket就都應該處於關閉CLOSED狀態了。但這有兩個問題,
第一:我們沒有任何機制保證最後的一個ACK能夠正常送達
第二:網路上仍然有可能有殘餘的資料包(wandering duplicates,或老的重複資料包),我們也必須能夠正常處理。
假設最後一個ACK丟失了,伺服器會重發它傳送的最後一個FIN,所以客戶端必須維持一個狀態資訊,以便能夠重發ACK;如果不維持這種狀態,客戶端在接收到FIN後將會響應一個RST,伺服器端接收到RST後會認為這是一個錯誤。如果TCP協議能夠正常完成必要的操作而終止雙方的資料流傳輸,就必須完全正確的傳輸四次握手的四個節,不能有任何的丟失。這就是為什麼socket在關閉後,仍然處於 TIME_WAIT狀態,因為他要等待以便重發ACK。
如果目前連線的通訊雙方都已經呼叫了close(),假定雙方都到達CLOSED狀態,而沒有TIME_WAIT狀態時,就會出現如下的情況。現在有一個新的連線被建立起來,使用的IP地址與埠與先前的完全相同,後建立的連線又稱作是原先連線的一個化身。還假定原先的連線中有資料報殘存於網路之中,這樣新的連線收到的資料報中有可能是先前連線的資料報。為了防止這一點,TCP不允許從處於TIME_WAIT狀態的socket建立一個連線。處於TIME_WAIT狀態的socket在等待兩倍的MSL時間以後(之所以是兩倍的MSL,是由於MSL是一個數據報在網路中單向發出到認定丟失的時間,一個數據報有可能在傳送圖中或是其響應過程中成為殘餘資料報,確認一個數據報及其響應的丟棄的需要兩倍的MSL),將會轉變為CLOSED狀態。這就意味著,一個成功建立的連線,必然使得先前網路中殘餘的資料報都丟失了。
由於TIME_WAIT狀態所帶來的相關問題,我們可以透過設定SO_LINGER標誌來避免socket進入TIME_WAIT狀態,這可以透過傳送RST而取代正常的TCP四次握手的終止方式。但這並不是一個很好的主意,TIME_WAIT對於我們來說往往是有利的。