UdpClient ограниченный размер буфера?

У меня проблемы с UdpClient в C#. Я передаю аудио через Интернет между двумя клиентами.

На моем микрофоне с частотой дискретизации 16 кГц я отправляю UDP-пакеты со звуком по 6400 байт на пакет. Они никогда не проходят, за исключением последнего пакета, который обычно составляет около 1200-3400 с чем-то, так как я закрываю запись. Когда я снижаю частоту дискретизации до 8 кГц, я отправляю пакеты с полезной нагрузкой 3200 байт. Они всегда проходят по какой-то причине.

Так что в основном все, что выше 3200, испортится (точное число не проверял, но ...), с какой стати это? Я подумал, возможно, внутренний буфер UdpClient слишком мал или что-то в этом роде? Так как я использую потоковое аудио, пакеты часто отправляются.

ПОЛУЧАТЬ:

private void audioReceive(IAsyncResult asyn)
    {
        try
        {
            byte[] temp = audioSock.EndReceive(asyn, ref this.serverEP);
            this.waveProvider.AddSamples(temp, 0, temp.Length);

            this.textbox_display.Text = this.textbox_display.Text + " got bytes: " + temp.Length;
            audioSock.BeginReceive(new AsyncCallback(audioReceive), null);

        }
        catch (Exception ez)
        {
            MessageBox.Show("audioReceive: " + this.textbox_nick.Text + "        " +ez.ToString());
        }

    }

Я не могу найти явную ошибку. (Объект asyn для функции имеет значение null, кстати, мне не нужно использовать stateobject , но это не должно быть связано с этим)

Я знаю, что UDP ненадежен, но, учитывая, что каждый пакет размером 3200 проходит, а размер 6400 не пахнет для меня подозрительно, особенно с максимальным размером, что, 64 КБ?

Любые идеи?


person KaiserJohaan    schedule 16.12.2010    source источник


Ответы (3)


Пакеты, превышающие MTU (который, я думаю, составляет около 1500 байт), могут быть отброшены. Например, см. это. Похоже, вы можете столкнуться с какой-то формой этого. Чтобы позволить ему работать более надежно в различных средах, может быть лучше максимизировать отправку до 1472 байтов на пакет (чтобы учесть служебные данные пакета), а затем собрать их на принимающей стороне.

Или, может быть, просто используйте TCP/IP. Даже если некоторые потери допустимы, может быть довольно сложно заставить работать «простое» решение UDP. Я работаю над продуктом, который поддерживает обмен данными для UDP и TCP/IP, и (осведомленное предположение) реализация UDP требует примерно в 10 раз больше кода и намного сложнее. Конечно, в нашей ситуации никакая потеря данных недопустима, так что это несколько меняет ситуацию.

person Mark Wilkins    schedule 16.12.2010
comment
Судя по тому, что этот трафик идет через Интернет, это похоже на то, что происходит. - person Joe Doyle; 16.12.2010
comment
Чтобы расширить это, IP-пакеты, превышающие MTU, будут фрагментированы. Если все фрагменты прибывают в место назначения, они будут повторно собраны в исходный IP-пакет (содержащий исходную дейтаграмму UDP) на уровне IP. Если не все они прибудут, в UDP нет механизма для запроса повторной передачи, поэтому вся дейтаграмма будет потеряна. - person user207421; 16.12.2010

Вам гарантировано 576 байт (548 для полезной нагрузки UDP) с IPv4, но вам следует стараться не превышать 1472 байта (1444 UDP), по крайней мере, для большинства пользователей.

Вы можете проверить, какой размер MTU работает, используя ping, как описано здесь,

http://help.expedient.net/broadband/mtu_ping_test.shtml

libjingle использует безопасное значение по умолчанию 1280 байт (1252 UDP/IPv4, 1232 UDP/IPv6), которое соответствует гарантированному минимуму для IPv6,

http://code.google.com/p/libjingle/source/browse/branches/nextsnap/talk/session/tunnel/pseudotcpchannel.cc?spec=svn17&r=13

person Steve-o    schedule 16.12.2010

С 2014 года эта ссылка может быть лучшим ответом на этот вопрос:

Класс UdpClient.NET Справочный источник .

private const int MaxUDPSize = 0x10000;  
...
private byte[] m_Buffer = new byte[MaxUDPSize];
person Eido95    schedule 29.03.2015