2011-05-24 323 views
4

我有一個Windows服務,其中包括使用.NET System.Net.Sockets庫監聽來自遠程設備的傳入數據。下面的示例只有一個遠程設備每60秒推送一次數據。TCP套接字連接

每隔一段時間,該服務都會停止,並在服務器的Windows日誌中顯示一條消息(如下所示)。

The process was terminated due to an unhandled exception. 
    Exception Info: System.Net.Sockets.SocketException Stack: 
    at System.Net.Sockets.Socket.EndReceive(System.IAsyncResult) 
    at Uk.Co.RCID.MoteServer.Server.SocketListener.ReceiveCallback(System.IAsyncResult) 
    at System.Net.LazyAsyncResult.Complete(IntPtr) 
    at System.Net.ContextAwareResult.CompleteCallback(System.Object) 
    at System.Threading.ExecutionContext.runTryCode(System.Object) 
    at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode, CleanupCode, System.Object) 
    at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object) 
    at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) 
    at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object) 
    at System.Net.ContextAwareResult.Complete(IntPtr) at System.Net.LazyAsyncResult.ProtectedInvokeCallback(System.Object, IntPtr) 
    at System.Net.Sockets.BaseOverlappedAsyncResult.CompletionPortCallback(UInt32, UInt32, System.Threading.NativeOverlapped*) 
    at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32, UInt32, System.Threading.NativeOverlapped*) 

具有匹配這個事件起來的時間與我的最後一個日誌聲明,我已經發現,當遠程設備的時間(通常是短空連接到服務中出現了兩次這種致命的例外,它連接每60秒來推送數據)。這是我在系統崩潰之前的最後一條日誌語句。

2011-05-20 13:39:19,545 [6] INFO Uk.Co.RCID.MoteServer.Server.SocketListener [(null)] - Waiting for a connection... 
2011-05-20 13:39:19,545 [10] INFO Uk.Co.RCID.MoteServer.Server.SocketListener [(null)] - Connection established on [10.64.128.60:11000] 
2011-05-20 13:40:20,982 [6] INFO Uk.Co.RCID.MoteServer.Server.SocketListener [(null)] - Waiting for a connection... 
2011-05-20 13:40:20,982 [5] INFO Uk.Co.RCID.MoteServer.Server.SocketListener [(null)] - Connection established on [10.64.128.60:11000] 

不希望公佈的源代碼(如果需要的話我可以安排,但將需要刪除某些細節),套接字監聽代碼基於這個例子。

http://msdn.microsoft.com/en-us/library/5w7b7x5f.aspx

任何幫助是極大的讚賞。


大家好,

感謝您的答覆。

我在ReceiveCallback功能增加了更多的日誌記錄和異常處理,發現我的日誌文件今天上午以下...

2011-05-25 04:52:26,816 [5] INFO Uk.Co.RCID.MoteServer.Server.SocketListener [(null)] - Waiting for a connection... 
2011-05-25 04:52:26,816 [10] INFO Uk.Co.RCID.MoteServer.Server.SocketListener  [(null)] - Connection established on [10.64.128.60:11000] 
2011-05-25 04:53:26,841 [10] WARN Uk.Co.RCID.MoteServer.Server.SocketListener [(null)] - SocketException thrown in ReceiveCallback 
2011-05-25 04:53:26,841 [10] WARN Uk.Co.RCID.MoteServer.Server.SocketListener [(null)] - ErrorCode: [10054] 
2011-05-25 04:53:26,841 [10] WARN Uk.Co.RCID.MoteServer.Server.SocketListener [(null)] - System.Net.Sockets.SocketException (0x80004005): An existing connection was forcibly closed by the remote host at System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult) at Uk.Co.RCID.MoteServer.Server.SocketListener.ReceiveCallback(IAsyncResult ar) 

所以,關鍵是(如強調上述一些問題的答案)以捕捉ReceiveCallback函數中的例外情況,並確定它們是否足夠嚴重以殺死您的應用程序。

+0

在捕獲異常的'InnerException'屬性中是否存在內部異常?我認爲你的代碼中可能會有東西被拋出,你從套接字接收數據。 – Nick 2011-05-24 09:21:09

+0

不幸的是我沒有這個信息。由於很少發生錯誤,因此需要一些時間才能通過更多日誌記錄重新創建問題。我會嘗試用模擬遠程設備重新創建它。 – user767428 2011-05-24 09:28:20

回答

0

當客戶端連接無法從半打開狀態轉換到完全打開狀態時,EndAccept可以並且會引發異常。另外請注意,在監聽器關閉之後它會拋出ObjectDisposedException,所以您必須真正查看異常並根據出錯情況確定要執行的操作。

EndReceive當客戶端連接強制關閉時,通常會拋出異常,但您必須再次查看異常並根據拋出的異常確定要執行的操作。

+0

我在ReceiveCallback函數中添加了更多的日誌記錄,昨晚在我的日誌文件中發現了以下內容...... – user767428 2011-05-25 07:43:25

0

我會做的第一件事是檢查投擲的SocketExceptionErrorCode屬性的值。查找winsock error code list中的這個值,查看可能出錯的一些指示。

如果您發佈了錯誤代碼,那麼我可能會進一步提供幫助。

+0

感謝您的提示。我將添加更多日誌記錄以檢索迄今爲止請求的信息。 – user767428 2011-05-24 09:45:33

2

如果你的代碼如下樣品頗有淵源,那麼你真的應該有一個try-catch周圍:

int read = handler.EndReceive(ar);

ReceiveCallback功能,因爲它可以作爲套接字連接這樣簡單的事情越來越關閉,而你正在嘗試接收。

而不是殺死進程,你可能會繼續。

+0

由於遠程設備是嵌入式電子設備,因此可能會在此期間關閉連接。謝謝。 – user767428 2011-05-24 09:46:07

2

您應該始終使用所有回調方法中的catch (Exception err)DO記錄異常。

原因是在除主線程之外的任何其他線程中拋出的所有未處理的異常都會終止您的應用程序。

您應該在套接字回調中處理任何異常,就好像客戶端已斷開連接一樣。你當然可以得到像OutOfMemoryException這樣的致命異常,它會終止你的應用程序。但在大多數情況下,這是不可能的。