socket example code c udp winsock network-protocols

example - Los paquetes Winsock UDP se están descartando?



winsock example (6)

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 impreciso y puedo tratar de proporcionar más información. ¡Gracias!


¿Es posible que al leer este búfer se descarten los paquetes entrantes?

Los paquetes se pueden eliminar si llegan más rápido de lo que los lee.

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

Una opción es cambiar el protocolo de red: usar TCP o implementar algún reconocimiento + ''control de flujo'' usando UDP.

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

Si la CPU se utiliza al 100%, se necesita hacer menos trabajo por paquete o obtener una CPU más rápida (o usar multiprocesamiento y más CPU, si no lo está).

Si la CPU no es 100%, entonces quizás lo que está sucediendo es:

  • Lees un paquete
  • Hace algo de trabajo, que lleva x mseg de tiempo real, parte del cual se gasta bloqueado en otras E / S (por lo que la CPU no está ocupada, pero no se está utilizando para leer otro paquete)
  • Durante esos x mseg, llega una avalancha de paquetes y algunos se descartan

Una cura para esto sería cambiar 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.


El tamaño del búfer de sockets predeterminado en sockets de Windows es 8k o 8192 bytes. Utilice 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".


Los paquetes podrían perderse 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 en caso de falla en 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.


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.

¿Asumo que estás usando select () para sondear el socket? Por lo que sé, no puedo causar una caída.


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 threading, por ejemplo, con pthreads y utilizaría un patrón de consumidor productor para poner el datagrama entrante en cola en otro hilo y luego consumir desde allí, para que sus llamadas de recepción no se bloqueen y el búfer no se ejecute por completo

Tercer paso, modifique su protocolo de nivel de aplicación, permita paquetes por lotes y paquetes por lotes en el remitente para reducir la sobrecarga del encabezado UDP al enviar una gran cantidad de pequeños paquetes.

El 4º paso revisa la red, los interruptores, etc., que pueden darte resultados detallados sobre sus estadísticas de tráfico, desbordamientos de búfer, etc. - si eso está en juego, consigue 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 tasa de caída es nula


Sí, la pila puede dejar caer paquetes, silenciosamente, 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.