2010-01-06 66 views
11

看來,使用socket.Close()爲一個TCP套接字,並沒有完全關閉套接字。在下面的示例中,我試圖連接到端口9999處的example.com,該端口未打開,並在短暫超時後嘗試關閉套接字。Socket.Close並不真的關閉tcp socket嗎? (c#)

for (int i = 0; i < 200; i++) 
    { 
    Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
    sock.LingerState = new LingerOption(false, 0); 
    sock.BeginConnect("www.example.com", 9999, OnSocketConnected, sock); 
    System.Threading.Thread.Sleep(50); 
    sock.Close(); 
    } 

但是當我看看netstat的循環完成後,我發現有很多半開的插座:

TCP israel-xp:6506   www.example.com:9999 SYN_SENT 
    TCP israel-xp:6507   www.example.com:9999 SYN_SENT 
    TCP israel-xp:6508   www.example.com:9999 SYN_SENT 
    TCP israel-xp:6509   www.example.com:9999 SYN_SENT 

編輯 。好吧,一些情況下丟失。我正在使用beginconnect,因爲我期望套接字連接失敗(9999未打開),並且在我的真實代碼中,一旦定時器被設置,我就調用socket.Close()。 On OnSocketConnected我調用了EndConnect,它引發一個異常(試圖調用一個處理對象的方法)。 我的目標是在套接字連接階段有一個短暫的超時。

任何線索我在做什麼錯? 謝謝!

回答

14

它將關閉套接字的.NET部分。然而,根據TCP規範,操作系統必須保持套接字的較低級別信息點打開一段時間以檢測重傳等。在這種特殊情況下,爲了檢測對發送的SYN數據包的回覆,可能需要稍微保持一段時間,以便它可以更明智地回覆,而不會與發送的其他數據包混淆在一起。

+2

這是有道理的,但不是徘徊於虛假應該解決嗎? – r0u1i 2010-01-06 18:22:29

+0

哦,逗留不這樣做。所以,沒有辦法讓Windows終止套接字。 – r0u1i 2010-01-07 13:33:21

+1

默認情況下,它將在Windows真正關閉之前處於FIN_WAIT狀態4分鐘。更有意思的是,如果你重新打開另一個連接到相同的目的地/端口窗口將重用FIN_WAIT中匹配的連接。 – Jay 2010-08-25 19:35:48

10

你打電話給*Begin*Connect - 這樣做是異步的。你甚至可能試圖在連接之前關閉套接字 - 所以當它連接時,它仍然是開放的。

嘗試同步連接 - 或關閉OnSocketConnected,以便看到關閉真正連接的套接字的效果。

+0

看我的編輯。 我正在使用BeginConnect,並且在調用Close之前,我的實際代碼會等待超時。只需在這樣一個套接字上調用EndConnect(其中dest端口未打開),只需要很長時間即可完成。 或者換句話說,我要超時套接字連接階段之後X毫秒(而不是高得離譜數毫秒窗口在默認情況下)。 – r0u1i 2010-01-06 18:14:30

18

按照設計,您應該在關閉套接字之前始終調用Shutdown

mySocket.Shutdown(SocketShutdown.Both); 
mySocket.Close(); 

所以切實做好禁止發送和接收在插座上,這樣就不會被接受輸入的數據你已經關閉了它之後,即使操作系統仍然有控制權。

Jon Skeet也有一個觀點,即你打開連接異步,它可能實際上是連接,而你試圖關閉它。但是,如果您打電話給Shutdown,它將不會允許您收到信息,因爲您正在經歷。

編輯:只能Shutdown已經連接的插座,這樣你寫你的代碼牢記這一點。

+0

+1對Jon Skeet的回答發表評論。 :-) – 2010-01-06 18:15:30

+0

如果套接字尚未連接,則ShutDown會引發一種不安 - 這正是我的場景。 – r0u1i 2010-01-06 18:16:48

+0

然後你應該使用OnSocketConnected來調用它的ShutDown並關閉它,或者這樣的性質。 – 2010-01-06 18:40:09

0

您初始化在每個循環新的Socket ...帶* .close()關閉舊的,並在開始您創建一個新的具有相同的參數和以前的Socket。

+0

是的。但我看到更多的開放式套接字不止一個。 – r0u1i 2010-01-06 18:15:58