SocketException внутри UdpClient BeginReceive сбивает весь процесс даже при попытке / улове - PullRequest
1 голос
/ 31 октября 2019

У нас есть приложение .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)

Моя проблема действительно в том, что процесс завершается в случае первого исключения.

...