Быстрое получение данных из UDP - PullRequest
0 голосов
/ 21 декабря 2018

Во-первых, я знаю, что UDP - ненадежный транспортный механизм на сетевом уровне, и нет, я не могу переключить свое приложение на TCP.Теперь, когда у нас это не так, как надо ...

У меня возникла проблема, когда я не могу прочитать данные из моего UDP-клиента в свое приложение так, чтобы я мог видеть все полученные пакеты,Я могу убедиться, что пакеты поступают на машину с Wireshark, что устраняет проблему надежности сети.Я удалил почти все из своего кода и буквально все, что он делает, это подсчитывает пакеты, и я до сих пор не могу привести количество пакетов из Wireshark в соответствие с количеством пакетов, которое я считаю в своем приложении.Я перепробовал все, что я могу найти в Интернете, включая увеличение размера буфера, чтобы избежать заполнения буфера ядра (который, казалось, не имел никакого эффекта).Клиенты Udp должны быть способны отправлять как широковещательные, так и одноадресные пакеты, но должны обрабатывать только одноадресные ответы.

Эта проблема проявляется при обработке большого количества одноадресных ответов от разных конечных точек в течение короткого периода времени.(~ 200 в 1 секунду).Если ответы распределены больше, тогда проблем нет, но я не могу контролировать получателей.

Я прошу прощения за то, что код немного неаккуратный, поскольку я пробовал разные вещи, чтобырешить проблему и не удалось (очевидно).

Код для создания клиента:

UdpClient Udp = new UdpClient();
Udp.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer, 0x4000);
Udp.ExclusiveAddressUse = false;
Udp.EnableBroadcast = true;
Udp.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
Udp.Client.Bind(new IPEndPoint(A, 12345));
ReceiveDataAsync(Udp, ReceiveDataCallback);

Код для обработки данных (опять же, просто подсчет пакетов):

private static void ReceiveDataAsync(UdpClient Client, Action<UdpClient, UdpReceiveResult> Callback)
{
    Thread T = new Thread(() =>
    {
        try
        {
            while (true)
            {
                try
                {
                    IPEndPoint E = new IPEndPoint(IPAddress.Any, 12345);
                    byte[] Data = Client.Receive(ref E);
                    PacketsFound += 1;
                }
                catch (SocketException)
                {
                    // Do nothing, triggered when we get ICMP unreachable.
                }
            }
        }
        catch (ObjectDisposedException)
        {
            // Do nothing
        }
        catch (NullReferenceException)
        {
            // Also do nothing.  Seems to fire when disposed and callback is still waiting.
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message + "\r\n\r\n" + ex.StackTrace, ex.GetType().ToString());
        }
    });
    T.IsBackground = true;
    T.Priority = ThreadPriority.Highest;
    T.Start();
}

Заранее благодарим за помощь.

...