¿Qué sucede si tengo un zócalo, s
, no hay datos actualmente disponibles en él, es un zócalo de bloqueo y llamo al recv
en dos hilos en ¿una vez? ¿Alguno de los hilos obtendrá los datos? ¿Ambos lo conseguirán? ¿La segunda llamada al recv
devolverá con un error?Llamada recv() en el mismo zócalo de bloqueo de dos hilos
Respuesta
Un hilo lo tendrá, y no hay forma de saber cuál.
Esto no parece un diseño razonable. ¿Hay alguna razón por la que necesite dos hilos llamando al recv()
en el mismo zócalo?
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:
garantía de un proveedor de hilo de seguridad puede significar simplemente que varios subprocesos pueden utilizar con seguridad cada uno sus propias tomas; no garantiza atomicity en una sola llamada, y no promete ninguna asignación particular de los datos del socket entre varios hilos.
Supongamos que el subproceso A llama a recv() en un socket que está recibiendo transmisión de datos TCP a gran 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, suponga que el subproceso A realiza un bloqueando llamada a recv() en un socket TCP, y los datos están entrando lentamente. Por lo tanto, la llamada a recv() regresa con errno establecido en EAGAIN.
En cualquiera de estos casos, suponga que el hilo B llama a recv() en el mismo socket mientras que 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.
Creo que estás equivocado sobre tus suposiciones aquí. recv() obtiene un paquete de datos y generalmente se usa con UDP, con TCP todavía obtiene un paquete de datos, pero a menos que sea muy cuidadoso en el lado del remitente, puede obtener el contenido de dos escrituras en un recv. –
De acuerdo, acabo de consultar los documentos y es un poco más complicado que un paquete según las banderas, pero eso es lo que he observado como el caso habitual en las aplicaciones de Linux en las que he trabajado. –
Los datagramas UDP son ciertamente más seguros que las secuencias TCP wrt threads. Sin embargo, no estoy seguro de que sean 100% seguras para hilos: si obtiene un EINTR (¿eso todavía sucede?), El hilo A vuelve de recv() prematuramente, lo que le da al hilo B la oportunidad de saltar. –
Desde el man page en recv
A recv() en un socket SOCK_STREAM vuelve mayor cantidad de información disponible como el tamaño de la memoria intermedia suministrado puede espera.
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, descartar los datos como no válidos o causar errores extraños y sutiles.
Ojalá pudiera decir que no sabía esto por experiencia.
Por lo tanto, aunque recv() en sí mismo es técnicamente seguro para subprocesos, es una mala idea tener dos hilos que lo llamen simultáneamente si lo está utilizando para TCP.
Por lo que sé, es completamente seguro cuando está usando UDP.
Espero que esto ayude.
- 1. zócalo Java sin bloqueo
- 2. ¿Son válidas las llamadas en paralelo para enviar/recv en el mismo zócalo?
- 3. select(), recv() y EWOULDBLOCK en sockets sin bloqueo
- 4. zócalo de programación: recv/problema de lectura de
- 5. MPI no bloqueo de envío/recv
- 6. Sockets C/C++ y un recv no de bloqueo()
- 7. Cómo implementar el bloqueo de lectura utilizando hilos POSIX
- 8. caso cuando el bloqueo de recv() devuelve menos de bytes solicitado
- 9. ¿Pueden los hilos escribir en diferentes elementos del mismo conjunto de estructuras sin bloqueo?
- 10. utiliza el mismo objeto de bloqueo en dos bloques de código diferentes?
- 11. bloqueo en una variable en múltiples hilos
- 12. cómo iniciar dos hilos al mismo tiempo (o en el momento de cierre)
- 13. Hilos OpenMP ejecutándose en el mismo núcleo de la CPU
- 14. ¿Qué determina cuál de los dos hilos que compiten adquiere un bloqueo?
- 15. cómo interrumpir un hilo que está esperando la función recv?
- 16. Aborto simultáneo() en dos hilos
- 17. Programación del zócalo en el nivel bajo
- 18. Dos procesos de lectura/escritura en el mismo archivo Python
- 19. Hacer que los hilos tengan el mismo número de timeslices
- 20. Comunicación entre dos hilos
- 21. bloques `pthread_mutex_trylock` cuando son llamados por dos hilos al mismo tiempo
- 22. scala actors vs hilos y bloqueo IO
- 23. Interrupción de dos pthreads de bloqueo mediante señales
- 24. Diccionario de bloqueo dentro del mismo hilo
- 25. Seleccionar() llamada al sistema en hilos?
- 26. Ejecutando múltiples hilos al mismo tiempo
- 27. entendimiento sincronización de hilos de bloqueo y no Thread.MemoryBarrier
- 28. recv con MSG_NONBLOCK y MSG_WAITALL
- 29. Múltiples hilos que iteran en el mismo mapa
- 30. Devolución de llamada WCF, proxy y seguridad de hilos
no, lo estoy implementando para un proyecto y quería saber qué debería pasar – Claudiu
lo pregunté porque no veo una buena razón para diseñarlo de esa manera. Uno de los beneficios de enhebrar es aislar cosas como enchufes para simplificar el manejo. Compartir lecturas en un socket entre hilos introduce mucha complejidad en su lugar. – dwc
Leer desde el mismo socket desde dos hilos tiene sentido si es un socket UDP para un protocolo sin conexión como DNS. Cada subproceso luego funciona de manera independiente en las solicitudes entrantes. – bdonlan