问题描述
我们有一个 .Net 应用程序作为服务运行,使用 TCPClient 在 TCP 端口上侦听流量。它可以成功运行数天和数千个连接,但在某些时候, 该服务在 Windows 事件查看器中因此异常而崩溃:
问题的签名:
Application: WindowsService.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.Net.sockets.socketException
at System.Net.sockets.socket.BeginReceive(Byte[],Int32,System.Net.sockets.socketFlags,System.AsyncCallback,System.Object)
at WindowsService.Connexion.AcceptCallback(System.IAsyncResult)
at System.Net.LazyAsyncResult.Complete(IntPtr)
at System.Net.ContextAwareResult.CompleteCallback(System.Object)
at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext,System.Threading.ContextCallback,System.Object,Boolean)
at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext,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,System.Threading.NativeOverlapped*)
先谢谢你:)
解决方法
Simali,欢迎来到 Stackoverflow。
首先,当您发布问题时,要求将代码发布到您的问题而不是评论中。 StackOverflows 允许您编辑您的问题。这次,我将您的代码添加到我的答案中:
private static void AcceptCallback(IAsyncResult AR) {
Socket socket;
try {
socket = serverSocket.EndAccept(AR);
Log.CreatLog("Client connected,server waiting for request ... ");
socket.BeginReceive(buffer,BUFFER_SIZE,SocketFlags.None,ReceiveCallbackAsync,socket);
serverSocket.BeginAccept(AcceptCallback,null);
}catch (ObjectDisposedException e) {
Log.CreatLog("ObjectDisposedException !!!"); return;
}
}
现在,正如您的堆栈错误所示,错误位于 socket.BeginReceive
并且抛出的异常为 SocketException
,这是 BeginReceive
可以抛出的四种不同异常之一:
- ArgumentNullException
- SocketException,表示:尝试访问套接字时出错。
- ObjectDisposedException
- ArgumentOutOfRangeException
可以在此link中查看此信息。
您的程序崩溃了,因为您处理的是 ObjectDisposedException
而不是其他的,例如本例中的 SocketException
。因此,您应该添加 SocketException
并打印程序在异常发生时遇到的消息和堆栈错误;像这样:
private static void AcceptCallback(IAsyncResult AR) {
Socket socket;
try {
socket = serverSocket.EndAccept(AR);
Log.CreatLog("Client connected,null);
}catch (ObjectDisposedException e) {
Log.CreatLog("ObjectDisposedException !!!" + e); return;
}
catch (SocketException e) {
Log.CreatLog("SocketException !!!: " + e); return;
}
catch (ArgumentOutOfRangeException e) {
Log.CreatLog("ArgumentOutOfRangeException !!!" + e); return;
}
catch (ArgumentNullException e) {
Log.CreatLog("ArgumentNullException !!!" + e); return;
}
}
我添加了其他例外,因为我不知道您的程序是否有其他套接字接收问题。
通过这种方式,您将获得有关错误的更多信息,并且您的程序将有更多机会通过异常。
重要:与此异常在 socket.BeginReceive
出现的情况相同,您可以在此函数中设置更多异常,例如 BeginAccept。所以我建议你检查异步套接字抛出的所有可能的异常并处理它们。