2012-09-06 16 views
8

Nunca había usado UDP antes, así que lo intenté. Para ver qué pasaría, el 'servidor' enviaba datos cada medio segundo y el cliente recibía datos cada 3 segundos. Entonces, aunque el servidor está enviando datos mucho más rápido de lo que el cliente puede recibir, el cliente aún lo recibe todo uno por uno.¿Dónde se almacenan los datos enviados por UDP?

¿Alguien puede explicar por qué/cómo sucede esto? ¿Dónde se almacenan los datos exactamente?

Enviar

class CSimpleSend 
{ 
    CSomeObjServer obj = new CSomeObjServer(); 

    public CSimpleSend() 
    { 
     obj.changedVar = varUpdated; 
     obj.threadedChangeSomeVar(); 
    } 

    private void varUpdated(int var) 
    { 
     string send = var.ToString(); 
     byte[] packetData = System.Text.UTF8Encoding.UTF8.GetBytes(send); 

     string ip = "127.0.0.1"; 
     int port = 11000; 

     IPEndPoint ep = new IPEndPoint(IPAddress.Parse(ip), port); 
     Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); 
     client.SendTo(packetData, ep); 

     Console.WriteLine("Sent Message: " + send); 
     Thread.Sleep(100); 
    } 
} 

Todo CSomeObjServer no se incrementa un entero por uno cada medio segundo

Recibe

class CSimpleReceive 
{ 
    CSomeObjClient obj = new CSomeObjClient(); 

    public Action<string> showMessage; 
    Int32 port = 11000; 
    UdpClient udpClient; 


    public CSimpleReceive() 
    { 
     udpClient = new UdpClient(port); 

     showMessage = Console.WriteLine; 
     Thread t = new Thread(() => ReceiveMessage()); 
     t.Start(); 
    } 

    private void ReceiveMessage() 
    {      
     while (true) 
     { 
      //Thread.Sleep(1000); 
      IPEndPoint remoteIPEndPoint = new IPEndPoint(IPAddress.Any, port); 
      byte[] content = udpClient.Receive(ref remoteIPEndPoint); 

      if (content.Length > 0) 
      { 
       string message = Encoding.UTF8.GetString(content); 
       if (showMessage != null) 
        showMessage("Recv:" + message); 

       int var_out = -1; 
       bool succ = Int32.TryParse(message, out var_out); 
       if (succ) 
       { 
        obj.alterSomeVar(var_out); 
        Console.WriteLine("Altered var to :" + var_out); 
       } 
      } 
      Thread.Sleep(3000); 
     } 
    } 
} 

tiendas CSomeObjClient la variable y tiene una función (alterSomeVar) para actualizarlo

salida de la señal:

Sent Message: 1 
Recv:1 
Altered var to :1 
Sent Message: 2 
Sent Message: 3 
Sent Message: 4 
Sent Message: 5 
Recv:2 
Altered var to :2 
Sent Message: 6 
Sent Message: 7 
Sent Message: 8 
Sent Message: 9 
Sent Message: 10 
Recv:3 
Altered var to :3 
+3

Aplaudo su naturaleza inquisitiva, 1 – spender

+1

el sistema operativo tiene una pila de red que por lo general tiene algunos búferes ... siempre que lo que envíe encaje en esos búferes no hay problema ... ya que UDP no está garantizado de todos modos los datos pueden descartarse, etc. – Yahia

+0

¿Se ejecutan el cliente y el servidor en la misma máquina? – grieve

Respuesta

3

El kernel del sistema operativo mantiene buffers de envío y recepción separados para cada socket UDP y TCP. Si busca en google SO_SNDBUF y SO_RCVBUF, encontrará mucha información al respecto.

Cuando envía datos, se copia desde su espacio de aplicación en el búfer de envío. A partir de ahí, se copia en la tarjeta de interfaz de red y luego en el cable. El lado de recepción es el reverso: NIC para recibir buffer, donde espera hasta que lo lea. Además, también pueden producirse copias y almacenamiento en búfer, según el sistema operativo.

Es fundamental tener en cuenta que los tamaños de estos almacenamientos intermedios pueden variar radicalmente. Algunos sistemas pueden tener un valor predeterminado de tan solo 4 kilobytes, mientras que otros brindan 2 megabytes. Puede encontrar el tamaño actual usando getsockopt() con SO_SNDBUF o SO_RCVBUF y también configurarlo usando setsockopt(). Pero muchos sistemas limitan el tamaño del búfer, a veces a cantidades arbitrariamente pequeñas. Este es típicamente un valor de kernel como net.core.wmem_max o net.core.rmem_max, pero la referencia exacta variará según el sistema.

También tenga en cuenta que setsockopt() puede fallar incluso si solicita una cantidad inferior al límite supuesto. Para obtener realmente el tamaño deseado, debe llamar repetidamente al setsockopt() con cantidades decrecientes hasta que finalmente tenga éxito.

La página siguiente es una nota técnica de mi empresa que toca este tema un poco y proporciona referencias para algunos sistemas comunes: http://www.dataexpedition.com/support/notes/tn0024.html

+0

¡Buena respuesta, gracias! – natli

0

A mi me parece como el UdpClient-Class proporciona una memoria intermedia para los datos recibidos. Intenta usar un socket directamente. También es posible que desee establecer los sockets ReceiveBufferSize en cero, aunque creo que solo se usa para conexiones TCP.

Cuestiones relacionadas