我有一个Windows服务,除其他外,它使用.NET System.Net.Sockets库侦听来自远程设备的传入数据。下面的示例只有一个远程设备每60秒推送一次数据。
每隔一段时间,此服务就会停止,并且服务器的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 :(得分:2)
如果你的代码非常接近于样本,那么你应该真的有一个试用:
int read = handler.EndReceive(ar);
ReceiveCallback
函数中的因为它可能就像你试图接收时套接字连接被关闭一样简单。
而不是杀死这个过程,你可能只是继续。
答案 1 :(得分:2)
在所有回调方法中,您应始终catch (Exception err)
。 DO 记录异常。
原因是在主线程之外的任何其他线程中抛出的所有未处理的异常都将终止您的应用程序。
您应该将套接字回调中的任何异常视为客户端已断开连接。您当然可以获得应该终止您的应用程序的致命异常,例如OutOfMemoryException
。但在大多数情况下,这不太可能。
答案 2 :(得分:0)
我要做的第一件事是检查抛出的ErrorCode
中SocketException
属性的值。在winsock error code list中查找此值,以获取可能出错的指示。
如果您发布错误代码,那么我可能会进一步提供帮助。
答案 3 :(得分:0)
当客户端连接无法从半开状态转换为完全打开状态时,EndAccept可以并且确实会抛出异常。另请注意,在侦听器关闭后它将抛出ObjectDisposedException
,因此您必须实际查看异常,并根据出错的情况确定要执行的操作。
EndReceive
通常会抛出,但是你必须再次查看异常并根据引发的异常确定要做什么。