2014-09-12 43 views
1

由於沒有指定Close方法是線程安全的,我應該從鎖中調用它。我如何確定它不會阻止我的線程?我應該禁用LingerState還是可以啓用?有沒有任何情況下,當TcpClient.Close或Socket.Close(0)可以阻止我的代碼?

btw我需要同時調用TcpClient.Close和TcpClient.Client.Close?

+0

您是否考慮過將套接字代碼放入其自己的線程中?或者也許使用TPL? – NathanAldenSr 2014-09-12 15:05:47

+1

在高性能服務器環境中,每次有新連接時都無法分配新線程。 – Vlad 2014-09-12 15:07:57

回答

2

根據documentation for TcpClient.Close,調用此方法處置實例。在ILSpy中快速瀏覽一下,它只需調用Dispose,即Dispose(true)

此外,該文件指出,致電Close也會處置底層Socket

事實上,在處置Socket之前,它調用Shutdown(SocketShutdown.Both)

鑑於.NET套接字是Windows套接字包裝,該shutdown功能也被稱爲,它的文檔狀態:

注意關機功能也不會因SO_LINGER設置阻止在插座上。

然而,Socket重載其Close方法接受超時參數和類似TcpClient,將Socket.Close方法調用Socket.Dispose(true),它使用超時值,以確定它是否可能阻塞。

按照documentation for Socket.Close(int)

如果您需要調用Close,而不首先調用shutdown,可以確保數據排隊傳出傳輸將通過設置DontLinger選項設置爲false,並指定不發送零超時間隔。關閉將阻塞,直到發送數據或直到指定的超時過期。如果將DontLinger設置爲false並指定零超時間隔,則Close會釋放連接並自動丟棄傳出的排隊數據。

顯然,無論是TcpClientSocket超時值暴露你作爲一個可設置屬性,默認值不0;因此,爲避免阻塞您似乎必須在致電TcpClient.Close之前自己致電Socket.Close(0)

請注意,Close也可以拋出SocketException,儘管框架設計指南的建議是不要致電Dispose。也許這就是它被命名爲CloseTcpClient明確實施Dispose方法的原因之一。

+0

我檢查瞭如果我使用TcpClient.Client.Close(1000)它會阻止。但是,如果我設置TcpClient.LingerState(true,1000),它不會阻止當我調用TcpClient.Close()或TcpClient.Client。關閉()沒有參數。這是否意味着我仍然可以使用逗留選項,但避免阻塞(使用Close()簡單關閉TcpClient)? – Vlad 2014-09-12 18:09:40

+0

當您測試時,緩衝區中是否有尚未發送的數據? – 2014-09-12 20:09:46

+0

在我看來,除非明確指定關閉(0),否則有可能會阻塞。 – 2014-09-12 20:12:08

相關問題