У нас есть приложение .Net, работающее как служба, которая прослушивает UDP-порт для трафика с использованием UdpClient. Он может успешно работать в течение нескольких дней и тысяч соединений, но в какой-то момент происходит сбой службы, за исключением этого в средстве просмотра событий Windows:
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.DoBeginReceiveFrom(Byte[], Int32, Int32, System.Net.Sockets.SocketFlags, System.Net.EndPoint, System.Net.SocketAddress, System.Net.Sockets.OverlappedAsyncResult)
at System.Net.Sockets.Socket.BeginReceiveFrom(Byte[], Int32, Int32, System.Net.Sockets.SocketFlags, System.Net.EndPoint ByRef, System.AsyncCallback, System.Object)
at System.Net.Sockets.UdpClient.BeginReceive(System.AsyncCallback, System.Object)
at OurNamespace.OurService.DataReceived(System.IAsyncResult)
at System.Net.LazyAsyncResult.Complete(IntPtr)
at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
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*)
Наш код обработки полученных данных довольно прост и стандартен:
private void StartListen()
{
if (UdpServer != null)
{
UdpServer.Close();
UdpServer = null;
}
UdpServer = new UdpClient(new IPEndPoint(IPAddress.Any, ListenPort));
UdpServer.BeginReceive(DataReceived, UdpServer);
}
private void DataReceived(IAsyncResult ar)
{
var c = (UdpClient) ar.AsyncState;
try
{
var receivedIpEndPoint = new IPEndPoint(IPAddress.Any, ListenPort);
var receivedBytes = c.EndReceive(ar, ref receivedIpEndPoint);
if (receivedBytes.Any())
Task.Factory.StartNew(() => InternalExecute(receivedBytes, receivedIpEndPoint));
// Restart listening
c.BeginReceive(DataReceived, ar.AsyncState);
}
catch (Exception ex)
{
ex.Log();
StartListen();
}
}
Я выполнил быстрый поиск в Интернете, и существует множество причин, чтобы иметь SocketException при программировании сокетов, но я не могу найти ничего, связанного с этим конкретным стеком вызовов и завершением процесса.
Просто доказательство того, что обработка исключений работает, мы также часто регистрируем эту строку в нашем обработчике исключений без завершения процесса (обычный случай прерывания соединения, не о чем беспокоиться):
System.Net.Sockets.SocketException (0x80004005): An existing connection was forcibly closed by the remote host
at System.Net.Sockets.Socket.EndReceiveFrom(IAsyncResult asyncResult, EndPoint& endPoint)
at System.Net.Sockets.UdpClient.EndReceive(IAsyncResult asyncResult, IPEndPoint& remoteEP)
at OurNamespace.OurService.DataReceived(IAsyncResult ar)
Моя проблема действительно в том, что процесс завершается в случае первого исключения.