使用Accept方法創建的TcpClient實例用於管理客戶端連接。當我需要終止服務器線程時會出現問題,因爲它在接收呼叫時被阻止。處理阻塞.NET套接字的超時時間
因此,我設置了一個TcpClient ReceiveTimeout以循環每個n毫秒來測試退出條件。結果是Receive操作引發了一個具有錯誤代碼SocketError.TimedOut的異常(SocketException)。好,我在想......
的問題是,Socket.Connected返回false,但作爲MSDN文檔中規定的屬性:
Connected屬性的值反映了作爲連接的狀態最近的操作。如果您需要確定連接的當前狀態,請進行非阻塞的零字節發送呼叫。如果調用成功返回或拋出WAEWOULDBLOCK錯誤代碼(10035),那麼套接字仍然連接;否則,套接字不再連接。
所以,我做什麼規定:
try {
// Receive operation on socket stream
// Send operation on socket stream
} catch (SocketException e) {
if (e.SocketErrorCode == SocketError.TimedOut) {
try {
IAsyncResult asyncResult;
int sResult;
asyncResult = mSocket.Client.BeginSend(new byte[] {}, 0, 0, SocketFlags.None, delegate(IAsyncResult result) { }, null);
sResult = mSocket.Client.EndSend(asyncResult);
Debug.Assert(asyncResult.IsCompleted == true);
if (mSocket.Connected == false)
throw new Exception("not more connected"); // Always thrown
} catch (Exception e) {
// ...
}
}
但是,即使執行aynch發送操作,財產mSocket.Connected永遠是假的,導致外環終止(其它線程調用Disconnect方法來終止服務器線程)。
我錯過了什麼?
恭候您的第一個答案!但這正是我試圖避免的。對於使用非阻塞套接字,我會重構服務器邏輯並使每個網絡操作異步,而不會產生額外的線程。 「問題是如果發生超時TcpClient斷開連接」:它寫在哪裏?在stdc非阻塞套接字中,在超時(使用select實現)之後,不會斷開連接。 – Luca 2010-08-26 13:20:44
我發佈的代碼使用異步BeginRead/EndRead函數。但它阻止使用WaitOne。所以你不必改變你的服務器邏輯。 BeginRead不會阻止。 WaitOne阻塞,直到出現數據或發生指定的超時。使用!result.IsCompleted來檢查它是否超時或有數據可用。 – pitt7 2010-08-26 14:07:25
我不知道「如果發生超時,TcpClient斷開連接」在哪裏寫入。但我有完全相同的問題。如果Read由超時返回,則連接爲False。我沒有對此做過多的研究,只是認爲C#中並沒有設置超時值,並定期運行到這個超時。 – pitt7 2010-08-26 14:11:04