TCP 套接字连接
我有一个 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 函数内,确定它们是否严重到足以终止您的应用程序。
I have a windows service which, amongst other things, listens for incoming data from a remote device using the .NET System.Net.Sockets library. The example below only has one remote device pushing data every 60 seconds.
Every so often, this service will stop and a message (shown below) will appear in the windows logs of the server.
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*)
Having matched the timing of this event up with my last log statement, I have discovered that this fatal exception occurs when the remote device connects to the service twice in a short space of time (typically, it connects every 60 seconds to push data). Here is my last log statement before the system crashes.
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]
Without wanting to publish the source code (I can arrange if required, but will need to remove certain details), the socket listening code is based on this example.
http://msdn.microsoft.com/en-us/library/5w7b7x5f.aspx
Any help is greatly appreciated.
Hi Everyone,
Thanks for you responses.
I added more logging and exception handling in the ReceiveCallback
function and found the following in my log file this morning...
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)
So, the key is (as highlighted in some of the answers above) to catch the exceptions inside the ReceiveCallback
function and decide if they are severe enough to kill your application.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
如果您的代码非常接近示例,那么您确实应该
添加一个 try-catch:
int read = handler.EndReceive(ar);
,在
ReceiveCallback
函数中 因为它可以就像您尝试接收时关闭套接字连接一样简单。您可以继续,而不是终止该进程。
If your code follows the sample quite closely then you should really have a try-catch around:
int read = handler.EndReceive(ar);
in the
ReceiveCallback
function because it could be something as simple as the socket connection getting closed while you're trying to receive.Rather than killing the process you can probably just continue.
您应该始终在所有回调方法中
catch (Exception err)
。 一定记录异常。原因是在主线程以外的任何其他线程中抛出的所有未处理的异常都会终止您的应用程序。
您应该将套接字回调中的任何异常视为客户端已断开连接。当然,您可能会遇到像
OutOfMemoryException
这样的致命异常,它们会终止您的应用程序。但大多数情况下这是不可能的。You should always
catch (Exception err)
in all callback methods. DO log the exception.The reason is that all unhandled exceptions thrown in any other thread than the main thread will terminate your application.
You should treat any exception in the socket callbacks as if the client has disconnected. You could of course get fatal exceptions like
OutOfMemoryException
that should terminate your application. But in most cases it's unlikely.当客户端连接无法从半打开状态转换到完全打开状态时,EndAccept 可以并且确实会引发异常。另请注意,它会在侦听器关闭后抛出
ObjectDisposeException
,因此您必须实际查看异常并根据出现的问题确定要执行的操作。EndReceive 通常在客户端连接强制关闭时抛出,但您必须再次查看异常并根据抛出的异常确定要执行的操作。
EndAccept can and does throw exceptions when a client connections fail to transition from half open to fully open states. Also note that it will throw an
ObjectDisposedException
after the listener is shutdown so you have to actually look at the exception and make a determination of what to do based on what went wrong.EndReceive
typically throws when the client connection closed forcibly, but again you have to look at the exception and make a determination of what to do based on what exception was thrown.我要做的第一件事是检查抛出的 SocketException 中的 ErrorCode 属性的值。在 winsock 错误代码列表中查找此值 获取一些可能出现问题的提示。
如果您发布错误代码,那么我可能可以提供进一步的帮助。
The first thing I would do is check the value of the
ErrorCode
property in the thrownSocketException
. Look-up this value in the winsock error code list for some pointers to what might be going wrong.If you post the error code then I might be able to help further.