2009-12-30 3 views
96
  1. Possiamo chiamare send da un thread e recv da un altro sullo stesso socket?
  2. Possiamo chiamare più mandate in parallelo da thread diversi sullo stesso socket?

So che un buon design dovrebbe evitare questo, ma non sono chiaro come si comportano queste API di sistema. Non riesco a trovare una buona documentazione anche per lo stesso.Le chiamate parallele per inviare/ricevere sullo stesso socket sono valide?

Qualsiasi suggerimento nella direzione sarà utile.

+0

perché affermi che fare questo è una cattiva pratica? Mi sta bene perché ascolti e ricevi da diversi thread. – TheMathNoob

risposta

72

POSIX definisce send/recv come operazioni atomiche, quindi supponendo che si parli di POSIX send/recv allora sì, si possono chiamare simultaneamente da più thread e le cose funzioneranno.

Ciò non significa necessariamente che verranno eseguiti in parallelo: nel caso di più mittenti, il secondo probabilmente bloccherà fino al completamento del primo. Probabilmente non ti accorgerai di questo, dato che una mandata termina quando ha messo i suoi dati nel buffer del socket.

Se si utilizzano i socket SOCK_STREAM, provare a fare le cose con un parallelo è meno probabile che sia utile in quanto send/recv potrebbe inviare o ricevere solo parte di un messaggio, il che significa che le cose potrebbero essere suddivise.

Blocco invio/recv su SOCK_STREAM socket solo blocco fino a quando non inviano o recuperano almeno 1 byte, quindi la differenza tra il blocco e il non blocco non è utile.

+0

E il blocco di send/recv? Sono atomici? – Jay

+0

questo articolo (http://www.almaden.ibm.com/cs/people/marksmith/sendmsg.html) sembra confermare ciò che dici di SOCK_STREAM ma non è chiaro su SOCK_DGRAM, da dove hai preso esattamente le tue informazioni? –

+1

@Joao: il socket SOCK_DGRAM è documentato come "preserving border boundaries", che non è molto chiaro. Osservando i sorgenti del kernel di Linux è possibile vedere almeno che ogni invio e recv gestisce atomicamente un singolo pacchetto (almeno per udp). –

2

Non vedo come ricevere in parallelo possa eventualmente realizzare qualcosa. Se hai un messaggio di 3 byte, 1 thread potrebbe ottenere i primi 2 byte e un altro l'ultimo byte, ma non avresti modo di dire quale fosse. A meno che i tuoi messaggi non siano lunghi solo un byte, non c'è modo di far funzionare in modo affidabile qualsiasi cosa con la ricezione di più thread.

Più manda potrebbe funzionare, se hai inviato l'intero messaggio in una singola chiamata, ma non sono sicuro. È possibile che uno possa sovrascrivere un altro. Certamente non ci sarebbe alcun vantaggio in termini di prestazioni.

Se è necessario inviare più thread, è necessario implementare una coda messaggi sincronizzata. Hanno un thread che fa l'invio vero e proprio che legge i messaggi dalla coda e che gli altri thread accodano messaggi interi. La stessa cosa funzionerebbe per la ricezione, ma il thread di ricezione avrebbe dovuto conoscere il formato dei messaggi in modo da poterli deserializzare correttamente.

+6

Se si utilizzano i socket SOCK_DGRAM, ogni recv riceverà un singolo datagramma; non sarà mai diviso tra i recvs –

+2

@noah, sono d'accordo che i recvs paralleli non possono realizzare nulla. Ecco perché non l'ho chiesto. La mia domanda è send/recv in parallelo e poi invia più parallelamente. La tua risposta fornisce una panoramica delle mandate parallele. Grazie per lo stesso. – Jay

+1

@Chris buon punto. Stavo assumendo TCP. @Jay Si potrebbe chiarire la domanda "Possiamo chiamare send/recv in parallelo" sembra che tu voglia ricevere in parallelo. – noah

11

Il descrittore del socket appartiene al processo, non a un thread specifico. Quindi, è possibile inviare/ricevere/dallo stesso socket in thread diversi, il sistema operativo gestirà la sincronizzazione.

Tuttavia, se l'ordine di invio/ricezione è semanticamente significativo, voi stessi (rispettivamente il vostro codice) devono garantire il corretto sequenziamento tra le operazioni nei diversi thread - come sempre accade con i thread.