2011-08-23 37 views
9

我正在做一些測試,試圖隔離庫(.NET)中的一些奇怪行爲。當我通過C++使用Winsock API並簡單地調用closesocket()時,我發現窗口端發送FIN/ACK數據包,遠端發送一個ACK數據包。這就是我所稱的優雅結尾。但是,當用C#編程時,我沒有看到我會稱之爲優雅的關閉。在C#中,我打開我的套接字,然後在關閉它時,我看到windows首先調用Socket.Shutdown()時發送一個FIN數據包只有。但是,無論如何,當我在C#中調用Socket.Close()時,都會發送一個RST數據包,並且連接立即被丟棄。這讓我感到困惑,因爲從我在線閱讀的內容來看,TCP關閉過程應該是FIN/ACK - > ACK(實際上雙方都是,但現在我只關心「我的」方面);即根本不應該有混合中的RST分組。從我讀過的內容來看,顯然,只有當接收者對連接狀態不確定並且想要出去時纔會發送RST數據包。如何防止.NET庫關閉發送RST數據包

爲什麼這個RST數據包是在.NET中按計劃關機發送的,而根本沒有在從winsock API計劃關機時發送?有沒有辦法阻止從.NET正常關機期間傳輸RST數據包?

如果重要,在兩個代碼路徑中,我在調用相應的close()方法之前先讀取套接字上的所有可用數據。

回答

0

剛剛遇到類似的問題,其中應用程序正在向POP3服務器通話POP3。當.NET程序完成時,它非正式關閉,Exchange將POP3對話視爲「中止」並將其回滾。

原因是我認爲TCP RST是一個「單向」消息 - 你不必等待回覆。所以這是.NET發送的內容(或者也許是終止後的任何程序),一個可行的辦法是關閉套接字後退出程序之前等待了一下:

Thread.Sleep(5000); 

這個工作對我前面提到的POP3問題;等待時間導致連接正常關閉,Exchange不再中止會話。

+1

這很有趣。我必須看到當我實施睡眠時會發生什麼。我不知道還會出現什麼,因爲我不認爲這是可行的(如果它的作品)在這種情況發生的全部背景。我製作了框架程序來隔離行爲。不過謝謝你,因爲我沒有想過在這裏使用睡眠電話。 –

3

讀的Socket.Close的.NET文檔,這是我發現:

對於面向連接的協議,建議您調用Close方法之前調用 關機。這確保所有數據 在關閉之前在連接的套接字上發送和接收。如果 需要在沒有首先調用Shutdown的情況下調用Close,則可以確保 通過將 DontLinger套接字選項設置爲false並指定非零超時 時間間隔來發送排隊等待傳出傳輸的數據。關閉將會阻塞,直到這個數據被髮送,或者直到 指定的超時時間到期。如果將DontLinger設置爲false,並指定 零超時間隔,則關閉釋放連接並自動丟棄傳出排隊數據。

這實際上是有意義的。如果緩衝區中存在數據(操作系統一),並且斷開連接或終止進程,連接將被重置(TCP規範中的更詳細信息)。

至於何時發送RST退房TCP Guide

我的猜測是,仍然有一些未設置或傳輸數據或觸發RST的輸出/輸入緩衝區。

1

以下代碼可能會阻止RST數據包。這是因爲在發送FIN數據包後等待60秒。

socket.Close(60); 

關閉方法描述是here