socket funcion crear como c sockets system recv

funcion - sockets en c



Llamar a recv() en el mismo socket de bloqueo de dos hilos (4)

¿Qué sucede si tengo un socket, s , no hay datos actualmente disponibles en él, es un socket de bloqueo y llamo a recv desde dos hilos a la vez? ¿Alguno de los hilos obtendrá los datos? ¿Ambos lo conseguirán? ¿La segunda llamada a recv regresará con un error?


Las implementaciones de socket deberían ser seguras para subprocesos, por lo que exactamente un subproceso debería obtener los datos cuando estén disponibles. La otra llamada debería simplemente bloquear.


No puedo encontrar una referencia para esto, pero aquí está mi entendimiento:

La garantía de un proveedor de seguridad de subprocesos puede significar solo que múltiples subprocesos pueden usar sus propios enchufes de manera segura; no garantiza la atomicidad a través de una sola llamada, y no promete ninguna asignación particular de los datos del socket entre múltiples hilos.

Supongamos que el subproceso A llama a recv () en un socket que está recibiendo datos de transmisión TCP a alta velocidad. Si recv () debe ser una llamada atómica, el hilo A podría bloquear la ejecución de todos los otros hilos, ya que debe ejecutarse continuamente para extraer todos los datos (hasta que el búfer esté lleno, de todos modos). Eso no sería así. bueno. Por lo tanto, no asumiría que recv () es inmune al cambio de contexto.

Por el contrario, supongamos que el subproceso A realiza una llamada de bloqueo a recv () en un socket TCP, y los datos entran lentamente. Por lo tanto, la llamada a recv () regresa con errno establecido en EAGAIN.

En cualquiera de estos casos, supongamos que el hilo B llama a recv () en el mismo socket mientras el hilo A aún está recibiendo datos. ¿Cuándo el hilo A deja de recibir datos para que el hilo B pueda comenzar a recibir datos? No sé de una implementación de Unix que intente recordar que el hilo A estaba en el medio de una operación en el socket; en cambio, depende de la aplicación (hilos A y B) negociar su uso.

En general, es mejor diseñar la aplicación para que solo uno de los hilos llame a recv () en un solo socket.


Un hilo lo obtendrá, y no hay forma de saber cuál.

Esto no parece un diseño razonable. ¿Hay alguna razón por la cual necesitas dos hilos que recv() a recv() en el mismo socket?


Desde la página man en recv

Un recv () en un socket SOCK_STREAM devuelve tanta información disponible como el tamaño del buffer provisto puede contener.

Supongamos que está utilizando TCP, ya que no se especificó en la pregunta. Entonces supongamos que tiene el hilo A y el hilo B bloqueando en recv () para socket s. Una vez que s tiene algunos datos para ser recibidos, desbloqueará uno de los hilos, digamos A, y devolverá los datos. Los datos devueltos serán de algún tamaño aleatorio en lo que a nosotros respecta. El subproceso A inspecciona los datos recibidos y decide si tiene un "mensaje" completo, donde un mensaje es un concepto de nivel de aplicación.

El subproceso A decide que no tiene un mensaje completo, por lo que vuelve a llamar a recv (). PERO mientras tanto B ya estaba bloqueando en el mismo zócalo, y ha recibido el resto del "mensaje" que estaba destinado para el hilo A. Estoy usando vagamente aquí.

Ahora tanto el hilo A como el hilo B tienen un mensaje incompleto y, según cómo se escriba el código, descartan los datos como no válidos o causan errores extraños y sutiles.

Ojalá pudiera decir que no sabía esto por experiencia.

Entonces, aunque recv () en sí mismo es técnicamente seguro para subprocesos, es una mala idea tener dos subprocesos llamándolo simultáneamente si lo está usando para TCP.

Por lo que yo sé, es completamente seguro cuando estás usando UDP.

Espero que esto ayude.