2009-02-25 57 views
1

我正在閱讀有關使用SO_LINGER套接字選項通過將逗留時間設置爲零來故意「暗殺」時間等待狀態的內容。然後,本書的作者繼續說,我們絕不應該這樣做,一般而言,我們絕不應該干涉等待時間的狀態。然後他立即建議使用SO_REUSEADDR選項來繞過時間等待狀態。TIME-WAIT Assassination和SO_REUSEADDR之間的區別是什麼

我的問題是,有什麼區別?在這兩種情況下,您都過早地終止了時間等待狀態,並冒着接收重複段的風險。爲什麼一個好的和另一個壞?

回答

1

我做了一些更多的閱讀,這是我發生了什麼(希望是正確的)理解:

當你調用close具有SO_REUSEADDR集(或您的應用程序崩潰)的插座上進行以下步驟:

  1. TCP發送發送緩衝區和FIN中的所有剩餘數據如果關閉被調用,它將立即返回而不指示,如果任何剩餘數據已成功傳送。
  2. 如果數據被髮送的對等體發送數據的ACK
  3. 對等體發送FIN的ACK,併發送它自己的FIN包
  4. 對等的FIN被ACKED和插座資源被釋放。
  5. 套接字不輸入TIME-WAIT。

當您關閉插座與SO_LINGER時間設置爲零:

  1. TCP丟棄發送緩衝區中的任何數據
  2. TCP發送一個RST包,以同行
  3. 插座資源被釋放。
  4. 的套接字不進入TIME-WAIT

所以超越的事實,設置靈兒爲零是一個黑客和不良作風它也是不禮貌的,因爲它沒有經過連接的正常關機。

2

TIME_WAIT是絕對正常的。它發生在本地端的TCP FIN之後,然後是來自遠程位置的TCP FIN ACK。在TIME_WAIT中,您只是在等待任何流浪包到達本地地址。但是,如果有丟失或丟失的數據包,則TIME_WAIT會確保在再次使用地址之前TTL或「生存時間」到期。

如果你使用SO_REUSEADDR,那麼你基本上說,我會假設沒有任何流浪數據包。現代可靠的TCP網絡越來越成爲可能。儘管這仍然是可能的,但不太可能。

將SO_LINGER設置爲零會導致您啓動異常關閉,也稱爲「關閉連接」。在這裏你不尊重TIME_WAIT並忽略一個流浪包的可能性。

如果您看到FIN_WAIT_1,那麼這可能會導致問題,因爲遠程位置未響應您的FIN發送TCP FIN ACK。所以這個過程被殺死或者TCP FIN ACK由於網絡分區或者壞路由而丟失。

當您看到CLOSE_WAIT時,您遇到問題,此時您正在泄漏連接,因爲您在給定TCP FIN時未發送TCP FIN ACK。

+0

除了使用逗留是一個黑客和壞風格的事實是什麼實際的區別?正如我所說,這兩個都消除了時間等待狀態。我唯一能想到的是,發送緩衝區中的任何數據都是在不等待ACK的情況下發送的 - 正如您所說的'關閉連接'一樣。 – 2009-02-26 20:21:26

+0

@ng。使用`SO_REUSEADDR`並不意味着忽略流氓TCP數據包。通常,它用於將TCP偵聽套接字綁定到端口,而連接(或TIME_WAIT中的舊連接)仍然存在。如果一個進程偵聽,則會出現這種情況,然後生成一個用於處理傳入連接的子進程,然後當連接仍在時,父進程將退出或死亡。爲了能夠重新啓動父代,需要`SO_REUSEADDR`這是非常安全的。請閱讀Stevens,Fenner和Rudoff(ISBN 0-13-14115-1)第210-213頁的「UNIX網絡編程第三版」。 – mgd 2013-01-23 12:38:33

0

我已經使用SO_REUSEADDR通配符bind()到一個其他程序已經打開了連接的本地端口。事實證明,只要沒有兩個套接字嘗試在同一個addr/port組合體上同時偵聽(),這個特殊的使用永遠不會導致問題。

相關問題