2011-12-10 41 views
6

Estoy usando System.Net.SocketsSocket clase para recibir los datagramas UDP. Quería saber la longitud exacta del datagrama recibido para verificar la validez del datagrama.tamaño del siguiente datagrama en cola - UDP

Socket.Receive(Byte()) documentación del método dice:

Si está utilizando una conexión de socket, reciben leerá el primer datagrama en cola desde la dirección de destino que especifique en el método Connect. Si el datagrama que recibe es más grande que el tamaño del parámetro del búfer, el búfer se llena con la primera parte del mensaje, el exceso de datos se pierde y se lanza una SocketException.

Socket.Available propiedad da el total de bytes disponibles para leer, Esto resume el tamaño de todos los datagramas en cola.

¿Hay alguna forma de averiguar el tamaño del siguiente datagrama?

public static void Receive() 
{ 
    Byte[] buf, discardbuf; 
    const int paklen = 32;     //correct packet length 
    int l; 

    buf = new Byte[paklen]; 
    discardbuf = new Byte[4096]; 

    while (rcv_enable) 
    { 
     l = soc.Available; 
     if (l == 0) continue; 
     if (l == paklen) soc.Receive(buf); //receive the correct packet 
     else soc.Receive(discardbuf);  //discard otherwise 
     Thread.Sleep(200); 
     Console.WriteLine("Received {0}", l); 
    }; 
} 

Respuesta

3

Voy a suponer que ha desarrollado su propio protocolo y espera datagramas de un tamaño conocido y desea protegerse contra los paquetes deshonestos.

Puesto que el rendimiento parece ser un problema y se quiere evitar excepciones tendría un vistazo a la overload of Receive que devuelve el error de conector directo en vez de lanzar excepciones. La documentación de MSDN sí (¿incorrectamente?) Dice que este método arrojará una excepción, pero no creo que sea así. Definitivamente vale la pena intentarlo.

SocketError error; 
byte[] buffer = new byte[512]; // Custom protocol max/fixed message size 
int c = this.Receive(buffer, 0, buffer.Length, SocketFlags.None, out error); 

if (error != SocketError.Success) 
{ 
    if(error == SocketError.MessageSize) 
    { 
     // The message was to large to fit in our buffer 
    } 
} 

usa un buffer de un tamaño cuerdo conocida previamente y utilizar la sobrecarga para comprobar el código de error SocketError con el fin de determinar si procede o no la lectura tuvo éxito o si sholud cae el paquete.

Si, sin embargo, su propio protocolo puede enviar datagramas de tamaños desconocidos hasta el límite del tamaño máximo de datagrama, no tiene otra opción que asignar un búfer lo suficientemente grande para ajustarse al paquete más grande (65k) (podría usar agrupación de búfer para evitar problemas de memoria dependiendo de su código).

Consulte también SocketFlags enum, contiene algunos miembros que pueden interesarle, como los miembros Parcial y Peek.

+0

¡Perfecto! Esta sobrecarga hace el trabajo y no se lanza ninguna excepción. Parece que la documentación de MSDN es incorrecta. Gracias.-BTW No pude encontrar ningún ejemplo relevante para [SocketFlags enum] (http://msdn.microsoft.com/en-us/library/system.net.sockets.socketflags.aspx) en MSDN. – Anniffer

+0

@Anniffer genial, no dude en aceptar esta respuesta si se resolvió su pregunta :) –

+0

Aceptado ..... :) – Anniffer

2

¿Por qué no comprobar el valor de retorno de Receive? Estoy bastante seguro de que cada llamada devolverá un datagrama.

+0

Funcionará, pero siempre necesito leer los datos en un búfer más grande. De lo contrario, si el búfer es menor que el tamaño del datagrama, Receive() arroja la excepción ** Código de error: 10040 ** _Un mensaje enviado en un socket de datagrama era más grande que el búfer de mensajes interno o algún otro límite de red, o el búfer utilizado para recibir un datagrama era más pequeño que el datagrama en sí. - en realidad este es un código de alto rendimiento, las excepciones son demasiado caras para arrojarlas y manejarlas – Anniffer

+0

Ah ok, desafortunadamente no soy experto en .NET pero una solución podría ser la solución MTU máximo de todas las interfaces en las que va a recibir datagramas. Otra solución es codificar el búfer en 65535 bytes, ya que es el tamaño máximo de datagrama UDP (campo de 16 bits de longitud), el máximo práctico real es un poco más pequeño, 65535 - encabezado IP - encabezado UDP. –

Cuestiones relacionadas