¿Son válidas las llamadas paralelas para enviar / recibir en el mismo socket?

127
  1. ¿Podemos llamar enviar desde un hilo y recibir desde otro en el mismo socket?
  2. ¿Podemos llamar a múltiples envíos en paralelo desde diferentes hilos en el mismo socket?

Sé que un buen diseño debería evitar esto, pero no tengo claro cómo se comportarán estas API del sistema. No puedo encontrar una buena documentación también para lo mismo.

Cualquier puntero en la dirección será útil.

Arrendajo
fuente
3
¿Por qué afirmas que hacerlo es una mala práctica? Me parece bien porque escuchas y recibes de diferentes hilos.
TheMathNoob

Respuestas:

92

POSIX define send / recv como operaciones atómicas, por lo tanto, suponiendo que esté hablando de POSIX send / recv, entonces sí, puede llamarlos simultáneamente desde múltiples hilos y las cosas funcionarán.

Esto no significa necesariamente que se ejecutarán en paralelo: en el caso de envíos múltiples, el segundo probablemente se bloqueará hasta que se complete el primero. Probablemente no se dará cuenta de esto, ya que un envío se completa una vez que coloca sus datos en el búfer de socket.

Si usa sockets SOCK_STREAM, es menos probable que sea útil hacer cosas en paralelo, ya que send / recv puede enviar o recibir solo una parte de un mensaje, lo que significa que las cosas podrían dividirse.

El bloqueo de envío / recepción en los sockets SOCK_STREAM solo bloquea hasta que envían o reciben al menos 1 byte, por lo que la diferencia entre bloqueo y no bloqueo no es útil.

Chris Dodd
fuente
1
@Joao: el socket SOCK_DGRAM está documentado como "preservar los límites del mensaje", lo que no está muy claro. Al mirar las fuentes del kernel de Linux, al menos puede ver que cada envío y recepción trata con un solo paquete atómicamente (al menos para udp).
Chris Dodd
2
@ Kedar: no estoy seguro de lo que quieres decir. A sendregresa tan pronto como los datos se colocan en el búfer de envío, y los datos se envían a través de la pila netowrk y salen a la red de forma asincrónica. Entonces, si tiene un subproceso de envío y un subproceso de recepción, es completamente posible (incluso probable) que el subproceso de envío envíe muchos paquetes antes de que el subproceso de recepción reciba el primer paquete. Es completamente asíncrono y no simultáneo.
Chris Dodd
66
@ChrisDodd, ¿puede dar un enlace para "POSIX define enviar / recibir como operaciones atómicas"?
suitianshi
2
@suitianshi: El documento estándar POSIX 1003.1c enumera todas las funciones en 1003.1 que son reentrantes (seguras para llamar desde subprocesos) y que no lo son. Lamentablemente, no conozco una copia gratuita en línea disponible en cualquier lugar.
Chris Dodd
2
@ChrisDodd He encontrado la copia en unix-systems.org/version4 y puedo ver la lista de la Tabla de interfaz del sistema en el capítulo 7.1, pero no veo dónde enumera las funciones como operaciones atómicas. No dudo de usted, pero ¿puede compartir / editar su respuesta para justificar su punto en el documento?
user153882
17

El descriptor de socket pertenece al proceso, no a un hilo particular. Por lo tanto, es posible enviar / recibir a / desde el mismo socket en diferentes subprocesos, el sistema operativo se encargará de la sincronización.

Sin embargo, si el orden de envío / recepción es semánticamente significativo, usted mismo (respectivamente, su código) debe garantizar una secuencia adecuada entre las operaciones en los diferentes subprocesos, como siempre ocurre con los subprocesos.

Adrian Willenbücher
fuente
4

No veo cómo recibir en paralelo podría lograr algo. Si tiene un mensaje de 3 bytes, 1 subproceso podría obtener los primeros 2 bytes y otro el último byte, pero no tendría forma de saber cuál fue cuál. A menos que sus mensajes solo duren un byte, no hay forma de que pueda hacer que algo funcione de manera confiable con la recepción de múltiples hilos.

Los envíos múltiples podrían funcionar, si envió el mensaje completo en una sola llamada, pero no estoy seguro. Es posible que uno pueda sobrescribir a otro. Ciertamente no habría ningún beneficio de rendimiento al hacerlo.

Si es necesario enviar varios subprocesos, debe implementar una cola de mensajes sincronizados. Tenga un hilo que realiza el envío real que lee los mensajes de la cola y haga que los otros hilos pongan en cola mensajes completos. Lo mismo funcionaría para recibir, pero el hilo de recepción tendría que conocer el formato de los mensajes para poder deserializarlos correctamente.

Noé
fuente
9
Si usa sockets SOCK_DGRAM, cada recv obtendrá un solo datagrama; nunca se dividirá entre recvs
Chris Dodd
2
@noah, estoy de acuerdo en que las grabaciones paralelas no pueden lograr nada. Por eso no lo he preguntado. Mi pregunta es enviar / recibir en paralelo y luego múltiples envíos en paralelo. Su respuesta da una idea de los envíos paralelos. Gracias por lo mismo.
Jay
1
@Chris buen punto. Estaba asumiendo TCP. @ Jay Puede aclarar que la pregunta "¿Podemos llamar a enviar / recibir en paralelo" suena como si quisiera recibir en paralelo.
noah