2011-05-24 184 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这样的致命异常,它会终止你的应用程序。但在大多数情况下,这是不可能的。