2009-10-02 20 views
9

Tenemos un sistema de comunicación cliente/servidor sobre la configuración de UDP en Windows. El problema al que nos enfrentamos es que cuando aumenta el rendimiento, los paquetes se eliminan. Sospechamos que esto se debe al búfer de recepción UDP que se está sondeando continuamente, lo que causa el bloqueo del búfer y la caída de cualquier paquete entrante. ¿Es posible que al leer este búfer se descarten los paquetes entrantes? Si es así, ¿cuáles son las opciones para corregir esto? El sistema está escrito en C. Por favor, hágame saber si esto es demasiado vago y puedo tratar de proporcionar más información. ¡Gracias!¿Se están cayendo los paquetes Winsock UDP?

+1

La naturaleza del UDP es la caída de paquetes bajo presión. Si desea una entrega confiable, use TCP. –

+2

De hecho, UDP tiene permiso para colocar, reordenar y duplicar sus paquetes en cualquier momento; hay una "garantía" de que no obtendrá paquetes dañados, pero en realidad lo verá también (la suma de comprobación de IP es bastante débil). – ephemient

+0

Noté lo mismo. Mi servidor de Linux transmite tan rápido que la ventana de Windows no puede seguir el ritmo ... ¡pero la máquina de Windows no es un entrenador lento! Voy a intentar aumentar los buffers – Matt

Respuesta

0

No estoy seguro de esto, pero en Windows, no es posible sondear el socket y hacer que un paquete caiga. Windows recoge los paquetes por separado de su sondeo y no debería causar ninguna caída.

supongo que está utilizando select() para sondear el zócalo? Por lo que sé, no puedo causar una caída.

+0

hmm ..gracias por la respuesta, supongo que necesitamos seguir investigando la causa de esto, entonces –

5

Sí, la pila puede dejar caer los paquetes — en silencio, incluso — cuando sus almacenamientos intermedios se llenan demasiado. Esto es parte de la naturaleza de UDP, uno de los bits de confiabilidad que abandona cuando cambia de TCP. Puede reinventar TCP — mal — agregando lógica de reintento, paquetes ACK, y demás, o puede cambiar a algo intermedio como SCTP.

Hay formas de aumentar el tamaño del búfer de la pila, pero eso en gran medida no tiene sentido. Si no está leyendo lo suficientemente rápido como para mantener el espacio del búfer disponible, hacer los búferes más grandes solo pospondrá el tiempo que le lleva quedarse sin espacio en el búfer. La solución adecuada es hacer búferes más grandes dentro de su propio código, y mover datos desde los búferes de la pila al búfer de su programa lo antes posible, donde puede esperar para ser procesado por tiempos arbitrariamente largos.

0

Los paquetes se pueden perder debido a un aumento en el tráfico de red no relacionado en cualquier punto de la ruta, o búferes de recepción completos. Para mitigar esto, puede aumentar el tamaño del búfer de recepción en Winsock.

Básicamente, UDP es un protocolo no confiable en el sentido de que la entrega de paquetes no está garantizada y no se devuelve ningún error al remitente cuando falla la entrega. Si está preocupado por la pérdida de paquetes, sería mejor implementar paquetes de confirmación en su protocolo de comunicación, o transferirlo a un protocolo más confiable como TCP. Realmente no hay otras maneras verdaderamente confiables de prevenir la pérdida de paquetes UDP.

3

¿Es posible que la lectura de este búfer provoque la caída de los paquetes entrantes?

Los paquetes pueden soltarse si llegan más rápido de lo que los ha leído.

Si es así, ¿cuáles son las opciones para corregir esto?

Una opción es cambiar el protocolo de red: use TCP o implemente algún acuse de recibo + 'control de flujo' usando UDP.

De lo contrario, debe ver por qué no lee rápido/con la frecuencia suficiente.

Si la CPU está 100% utilizada, entonces necesita hacer menos trabajo por paquete u obtener una CPU más rápida (o utilizar multiprocesamiento y más CPU si no lo está haciendo todavía).

Si la CPU no es 100%, entonces tal vez lo que está sucediendo es:

  • usted lee un paquete
  • usted hace un trabajo, que lleva x ms de tiempo real, algunos de los cuales se gasta bloqueado en algún otro I/O (por lo que la CPU no está ocupado, pero que no está siendo utilizado para leer otro paquete)
  • Durante los x mseg, una inundación de paquetes llegan y algunos se dejó caer

a cura para esto sería cambiar e el enhebrado.

Otra posibilidad es hacer varias lecturas simultáneas desde el socket (cada una de sus lecturas proporciona un búfer en el que se puede recibir un paquete UDP).

Otra posibilidad es ver si hay una opción de configuración (específica de O/S) para aumentar el número de paquetes UDP recibidos que la pila de red está dispuesta a almacenar en búfer hasta que intente leerlos.

12

El tamaño de búfer de sockets predeterminado en sockets de Windows es 8k o 8192 bytes. Use la función de Windows setsockopt para aumentar el tamaño del búfer (consulte la opción SO_RCVBUF).

Pero más allá de eso, aumentar el tamaño de su búfer de recepción solo retrasará el tiempo hasta que los paquetes se vuelvan a caer si no lee los paquetes lo suficientemente rápido.

Normalmente, desea dos hilos para este tipo de situación.

El primer hilo existe únicamente para reparar el socket. En otras palabras, el único propósito del hilo es leer un paquete del zócalo, agregarlo a algún tipo de estructura de datos compartidos correctamente sincronizada, señalar que se ha recibido un paquete y luego leer el siguiente paquete.

El segundo hilo existe para procesar los paquetes recibidos. Permanece inactivo hasta que el primer hilo indica que se recibió un paquete. Luego extrae el paquete de la estructura de datos compartidos correctamente sincronizada y lo procesa. Luego espera a ser señalado nuevamente.

Como prueba, intente poner en cortocircuito el procesamiento completo de sus paquetes y simplemente escriba un mensaje en la consola (o un archivo) cada vez que se haya recibido un paquete. Si puede hacerlo con éxito sin dejar caer los paquetes, entonces puede ser útil dividir su funcionalidad en un hilo "receptor" y un hilo "procesador".

3

Primer paso, aumentar el tamaño del búfer del receptor, Windows prácticamente concede todas las solicitudes de tamaño razonable.

Si eso no ayuda, su código de consumo parece tener algunas áreas bastante lentas. Yo usaría enhebrar, p. Ej. con pthreads y utiliza un patrón de consumidor productor para poner el datagrama entrante en cola en otro subproceso y luego consumir desde allí, para que sus llamadas de recepción no se bloqueen y el búfer no se ejecute completo

3er paso, modifique su aplicación nivel de protocolo, permite paquetes por lotes y paquetes por lotes en el remitente para reducir la carga general del encabezado UDP para enviar una gran cantidad de paquetes pequeños.

El cuarto paso revisa los engranajes de tu red, interruptores, etc., para darte información detallada sobre sus estadísticas de tráfico, desbordamientos de búfer, etc.- si eso está en juego, obtenga interruptores más rápidos o posiblemente cambie uno defectuoso

... solo fyi, estoy ejecutando el tráfico de multidifusión UDP en nuestro backend continuamente en avg. ~ 30Mbit/seg con picos de 70Mbit/sy mi índice de caída es nulo nulo

Cuestiones relacionadas