2017-02-20 3 views
0
public class RCon 
{ 
    static readonly ConcurrentQueue<byte[]> ReceivedPacketQueue = new ConcurrentQueue<byte[]>(); 
    static IPEndPoint _ipEndPoint = new IPEndPoint(IPAddress.Parse("10.XXX.XX.117"), 2222); 

    static void Main(string[] args) 
    { 
     var client = new UdpClient 
         { 
          ExclusiveAddressUse = false, 
          Client = { ReceiveBufferSize = 8192 } 
          }; 

     client.Client.Bind(_ipEndPoint); 
     client.BeginReceive(OnUdpData, client); 

     var message = new byte[100]; 
     int numberOfPackets ; 

     for (numberOfPackets = 0; numberOfPackets < 84; numberOfPackets++) 
     { 
      client.Send(message, message.Length, _ipEndPoint); 
     } 
    } 

    static void OnUdpData(IAsyncResult result) 
    { 
     var socket = result.AsyncState as UdpClient; 
     var message = socket.EndReceive(result, ref _ipEndPoint); 
     ReceivedPacketQueue.Enqueue(message); 
     socket.BeginReceive(OnUdpData, socket); 
    } 
} 

Я написал простую программу, которая отправляет пакеты по 100 байт и ту же машину, что и сервер, асинхронно принимает пакеты и сохраняет их в очереди. Полученные пакеты штрафуются до тех пор, пока количество пакетов не будет 83. Как только я начну увеличивать количество пакетов более 84, количество пропущенных пакетов падает. Насколько я понимаю, это связано с тем, что клиент не достаточно быстро читает входящие пакеты и по мере того, как буфер переполняется, пакеты теряются. Есть ли способ сделать сервер достаточно быстрым, чтобы получать быстрые входящие пакеты.C# udp сервер не читает достаточно быстро

Был аналогичный вопрос C# UDP packetloss though all packets arrive (WireShark) Я думаю, что я делаю то, что было предложено, но все еще проблема сохраняется.

+0

Выглядит, как вы отправляете сообщения к себе - от ф 10.170.25.117:2222 к внутрибрюшинно 10.170.25.117:222, а на самом деле я не знаю, как это будет работать в этой ситуации Try для установки обоих буферов отправки и приема на максимальное значение, то есть 65536 – Dmitry

+0

Спасибо, Дмитрий. Да, такая же машина работает как сервер и клиент. Даже если я установил максимальный размер буфера и увеличил скорость пакетов (от 84 до 1200 или большего числа), я начинаю потерять пакеты, так как чтение недостаточно быстро и происходит переполнение буфера. Мой вопрос - есть ли что-нибудь, что я могу улучшить, асинхронное начало получать (OnUdpData) код каким-либо образом, чтобы закрепить чтение пакетов. – devwork

ответ

0

Ну, он использует тот же IP-адрес в том же порту для сервера и клиента :)

Я сделал тест с вашим кодом. Я добавил 2 статических vars static int sendIter = 0; static int recvIter = 0;

и запустить приложение. Он выходит с sendIter = 84 и recvIter = 0..2-3 итерации

Я думаю, что это происходит из-за того, что вы запускаете операцию async (BeginReceive) в функции, а затем сразу же запускаете цикл для отправки msgs. Под капотом BeginReceive запускает поток, но у него нет шансов переключить контекст на себя, даже если он готов обрабатывать входящее сообщение из-за этого для цикла - он занимает все время процессора.

Затем я добавил Thread.Sleep (1) (это позволит приложению для переключения контекста потока) сразу после client.Send и я получил sendIter и recvIter равно

Так я думаю, что клиент достаточно, если быстро он имеет процессорное время

class Program 
{ 
    static readonly ConcurrentQueue<byte[]> ReceivedPacketQueue = new ConcurrentQueue<byte[]>(); 
    static IPEndPoint _ipEndPoint = new IPEndPoint(IPAddress.Parse("192.168.4.142"), 2222); 
    static int sendIter = 0; 
    static int recvIter = 0; 

    static void Main(string[] args) 
    { 
     var client = new UdpClient 
     { 
      ExclusiveAddressUse = false, 
      Client = { ReceiveBufferSize = 8192 } 
     }; 

     client.Client.Bind(_ipEndPoint); 
     client.BeginReceive(OnUdpData, client); 

     var message = new byte[100]; 
     int numberOfPackets; 

     for (numberOfPackets = 0; numberOfPackets < 100; numberOfPackets++) 
     { 
      client.Send(message, message.Length, _ipEndPoint); 
      Thread.Sleep(1); 
      sendIter++; 
     } 

     Console.WriteLine(sendIter); 
     Console.WriteLine(recvIter); 
     Console.ReadKey(); 
    } 

    static void OnUdpData(IAsyncResult result) 
    { 
     var socket = result.AsyncState as UdpClient; 
     var message = socket.EndReceive(result, ref _ipEndPoint); 
     ReceivedPacketQueue.Enqueue(message); 
     recvIter++; 
     socket.BeginReceive(OnUdpData, socket); 
    } 
} 
Смежные вопросы