由於沒有指定Close方法是線程安全的,我應該從鎖中調用它。我如何確定它不會阻止我的線程?我應該禁用LingerState還是可以啓用?有沒有任何情況下,當TcpClient.Close或Socket.Close(0)可以阻止我的代碼?
btw我需要同時調用TcpClient.Close和TcpClient.Client.Close?
由於沒有指定Close方法是線程安全的,我應該從鎖中調用它。我如何確定它不會阻止我的線程?我應該禁用LingerState還是可以啓用?有沒有任何情況下,當TcpClient.Close或Socket.Close(0)可以阻止我的代碼?
btw我需要同時調用TcpClient.Close和TcpClient.Client.Close?
根據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會釋放連接並自動丟棄傳出的排隊數據。
顯然,無論是TcpClient
或Socket
的超時值暴露你作爲一個可設置屬性,默認值不0
;因此,爲避免阻塞您似乎必須在致電TcpClient.Close
之前自己致電Socket.Close(0)
。
請注意,Close
也可以拋出SocketException
,儘管框架設計指南的建議是不要致電Dispose
。也許這就是它被命名爲Close
和TcpClient
明確實施Dispose
方法的原因之一。
我檢查瞭如果我使用TcpClient.Client.Close(1000)它會阻止。但是,如果我設置TcpClient.LingerState(true,1000),它不會阻止當我調用TcpClient.Close()或TcpClient.Client。關閉()沒有參數。這是否意味着我仍然可以使用逗留選項,但避免阻塞(使用Close()簡單關閉TcpClient)? – Vlad 2014-09-12 18:09:40
當您測試時,緩衝區中是否有尚未發送的數據? – 2014-09-12 20:09:46
在我看來,除非明確指定關閉(0),否則有可能會阻塞。 – 2014-09-12 20:12:08
您是否考慮過將套接字代碼放入其自己的線程中?或者也許使用TPL? – NathanAldenSr 2014-09-12 15:05:47
在高性能服務器環境中,每次有新連接時都無法分配新線程。 – Vlad 2014-09-12 15:07:57