Socket C: ¿Enviar espera a que finalice el recv?

Yo uso el locking de sockets C en Windows. Los uso para enviar actualizaciones de datos del servidor al cliente y viceversa. Envío actualizaciones a alta frecuencia (cada 100 ms). ¿La función send() esperará a que el receptor recv() reciba los datos antes de finalizar?

Supongo que no si entiendo bien la página del manual:

“La finalización exitosa de send () no garantiza la entrega del mensaje”.

Entonces, ¿qué pasará si uno está ejecutando 10 ocurrencias de send() mientras que el otro tiene solo 1 recv() ?

¿Necesito usar algún tipo de sistema de reconocimiento?

Supongamos que está utilizando TCP. Cuando llama al envío, los datos que está enviando se colocan inmediatamente en la cola de salida y se envían, luego, se completan correctamente. Sin embargo, si el envío no puede colocar los datos en la cola de salida, el envío volverá con un error.

Dado que Tcp es un protocolo de entrega garantizado, los datos en la cola de salida solo se pueden eliminar una vez que el extremo remoto haya recibido el acuse de recibo. Esto se debe a que es posible que sea necesario volver a enviar los datos si no se ha recibido un recibo a tiempo.

Si el extremo remoto es lento, la cola saliente se llenará con datos y el envío se bloqueará hasta que haya espacio para colocar los nuevos datos en la cola saliente.

Sin embargo, la conexión puede fallar de tal manera que no haya forma de que se puedan enviar más datos. Aunque una vez que se ha cerrado una conexión TCP, cualquier envío adicional resultará en un error, el usuario no tiene forma de saber cuánta información llegó al otro lado. (No conozco ninguna forma de recuperar la contabilidad TCP de un socket a la aplicación del usuario). Por lo tanto, si se requiere la confirmación de la recepción de datos, probablemente debería implementar esto en el nivel de la aplicación.

Para UDP, no hace falta decir que es una forma de informar lo que se recibió o no se recibió.

send() bloquea hasta que el sistema operativo (kernel) tome los datos y los coloque en un búfer de datos salientes. No espera hasta que el otro extremo haya recibido los datos.

Si está enviando por TCP, obtiene una entrega garantizada 1 y el otro extremo recibirá los datos en el pedido enviado. Sin embargo, eso podría unirse de manera que lo que usted envió como 10 actualizaciones separadas se recibiera como un paquete grande único (o viceversa, una única actualización podría dividirse en un número arbitrario de paquetes). Esto significa, entre otras cosas, que cualquier ACK de cualquier información acusa recibo de todos los datos anteriores.

Si está utilizando UDP, nada de eso es cierto: los datos pueden llegar a estar fuera de orden, o ser descartados y nunca entregados. Si le importa que se reciban todos los datos, solo necesita crear algún tipo de sistema de reconocimiento propio sobre UDP en sí.

1 Por supuesto, hay un límite en la garantía: si un cable de red se corta (o lo que sea), los paquetes no se entregarán, pero al menos aparecerá un mensaje de error que le informará que se perdió la conexión.

Si está utilizando TCP, obtiene los reconocimientos de forma gratuita, ya que eso es parte de lo que hace el protocolo bajo el capó. Pero suena como para este tipo de aplicación que probablemente querrás usar UDP. En cualquier caso, aunque send() no se bloqueará hasta que el cliente tenga éxito recv() .

Si es crucial que el cliente reciba todos los mensajes, entonces use TCP. Si está bien que el cliente pierda uno o más mensajes, entonces use UDP.

TCP garantiza la entrega en un nivel de stack TCP más bajo. Reintenta la entrega hasta que la parte receptora reconozca que se recibieron los datos, pero es posible que su aplicación nunca sepa sobre este hecho.

Digamos que está enviando trozos de datos y necesita colocar esos trozos de datos en algún lugar de acuerdo con alguna lógica. Si su aplicación no está preparada para saber dónde se debe colocar cada bloque individual, puede resultar inútil recibirlo en el nivel TCP. El post original fue sobre la lógica de nivel de aplicación.