Как я могу установить размер буфера для нижнего сокета UDP? C # - PullRequest
9 голосов
/ 09 марта 2010

Как мы знаем для получения UDP, мы используем Socket.ReceiveFrom или UdpClient.receive

Socket.ReceiveFrom принимает от вас байтовый массив для помещения данных udp.

UdpClient.receive возвращает непосредственно байтовый массив, где данные

Мой вопрос заключается в том, как установить размер буфера внутри сокета. Я думаю, что ОС поддерживает свой собственный буфер для приема данных UDP, верно? например, если пакет udp отправлен на мою машину, ОС поместит его в буфер и будет ждать нас в Socket.ReceiveFrom или UdpClient.receive, верно?

Как я могу изменить размер этого внутреннего буфера?

Я пробовал Socket.ReceiveBuffSize, он никак не влияет на UDP, и он ясно сказал, что это для окна TCP. Также я провел много экспериментов, которые доказывают, что Socket.ReceiveBufferSize НЕ для UDP.

Может кто-нибудь поделиться некоторыми соображениями о внутреннем буфере UDP ???

Спасибо

Я видел здесь несколько сообщений, например,

http://social.msdn.microsoft.com/Forums/en-US/ncl/thread/c80ad765-b10f-4bca-917e-2959c9eb102a

Дейв сказал, что Socket.ReceiveBufferSize может установить внутренний буфер для UDP. Я не согласен.

Эксперимент, который я провел, выглядит следующим образом:

27 хостов одновременно отправляют мне пакет локальной сети размером 10 КБ в локальной сети (по крайней мере, почти). У меня есть цикл while для обработки каждого пакета. Для каждого пакета я создаю поток и обрабатываю его. Я использовал UdpClient или Socket для получения пакетов.

Я потерял около 50% пакетов. Я думаю, что это взрыв UDP-отправки, и я не могу обработать их все вовремя.

Вот почему я хочу увеличить размер буфера для UDP. скажем, если я изменю размер буфера на 1 МБ, тогда 27 * 10 КБ = 270 КБ данные могут быть приняты в буфере, верно?

Я попытался изменить Socket.ReceiveBufferSize на множество значений, но он просто не имеет эффектов.

Кто-нибудь может помочь?

Ответы [ 2 ]

9 голосов
/ 09 марта 2010

Я часто использую .NET UDPClient и всегда использовал Socket.ReceiveBufferSize и получаю хорошие результаты. Внутренне он вызывает Socket.SetSocketOption с параметром ReceiveBuffer . Вот небольшой, быстрый код, который вы можете протестировать:

public static void Main(string[] args)
{
  IPEndPoint remoteEp = null;
  UdpClient client = new UdpClient(4242);
  client.Client.ReceiveBufferSize = 4096;

  Console.Write("Start sending data...");
  client.Receive(ref remoteEp);
  Console.WriteLine("Good");

  Thread.Sleep(5000);
  Console.WriteLine("Stop sending data!");
  Thread.Sleep(1500);

  int count = 0;
  while (true)
  {
    client.Receive(ref remoteEp);
    Console.WriteLine(string.Format("Count: {0}", ++count));
  }
}

Попробуйте настроить значение, переданное в ReceiveBufferSize. Я протестировал отправку постоянного потока данных в течение 5 секунд и получил 10 пакетов. Затем я увеличил х4, и в следующий раз получил 38 пакетов.

Я бы посмотрел в других местах вашей сети, где вы можете сбрасывать пакеты. Тем более что в своем другом сообщении вы упоминаете, что отправляете пакеты размером 10 КБ. 10 КБ будут фрагментированы при отправке в пакеты размером MTU. Если какой-либо 1 пакет в серии отброшен, весь пакет будет отброшен.

7 голосов
/ 13 марта 2012

Проблема с настройкой ReceiveBufferSize заключается в том, что вам нужно установить его непосредственно после создания объекта UdpClient. У меня была та же проблема с моими изменениями, которые не отражались при получении значения ReceiveBufferSize.

UdpClient client = new UdpClient()
//no code inbetween these two lines accessing client.
client.Client.ReceiveBufferSize = somevalue
...