Sono valide le chiamate parallele per inviare / ricevere sullo stesso socket?


127
  1. Possiamo chiamare send da un thread e recv da un altro sullo stesso socket?
  2. Possiamo chiamare più invii in parallelo da thread diversi sullo stesso socket?

So che un buon design dovrebbe evitarlo, ma non sono chiaro come si comporteranno queste API di sistema. Non riesco a trovare una buona documentazione anche per lo stesso.

Eventuali puntatori nella direzione saranno utili.


3
perché affermi che farlo è una cattiva pratica? Mi sembra perfetto perché ascolti e ricevi da diversi thread.
TheMathNoob

Risposte:


92

POSIX definisce send / recv come operazioni atomiche, quindi supponendo che tu stia parlando di POSIX send / recv, allora sì, puoi chiamarli simultaneamente da più thread e le cose funzioneranno.

Questo non significa necessariamente che verranno eseguiti in parallelo: in caso di invii multipli, il secondo probabilmente si bloccherà fino al completamento del primo. Probabilmente non ti accorgerai molto di questo, dato che un invio viene completato una volta che ha inserito i suoi dati nel buffer del socket.

Se stai usando i socket SOCK_STREAM, provare a fare cose che un parallelo ha meno probabilità di essere utile in quanto send / recv potrebbe inviare o ricevere solo una parte di un messaggio, il che significa che le cose potrebbero essere divise.

Il blocco dell'invio / recupero sui socket SOCK_STREAM si blocca solo fino a quando non inviano o ricevono almeno 1 byte, quindi la differenza tra blocco e non blocco non è utile.


1
@Joao: i socket SOCK_DGRAM sono documentati come "preservare i confini dei messaggi", il che non è molto chiaro. Osservando i sorgenti del kernel Linux si può almeno vedere che ogni send e recv si occupano atomicamente di un singolo pacchetto (almeno per udp).
Chris Dodd,

2
@Kedar: non sono sicuro di cosa intendi. A sendritorna non appena i dati vengono inseriti nel buffer di invio e i dati vengono inviati attraverso lo stack netowrk e inviati in rete in modo asincrono. Pertanto, se si dispone di un thread di invio e di un thread di ricezione, è del tutto possibile (anche probabile) che il thread di invio invii molti pacchetti prima che il thread di ricezione riceva il primo pacchetto. È completamente asincrono e non simultaneo.
Chris Dodd,

6
@ChrisDodd, puoi fornire un link per "POSIX definisce send / recv come operazioni atomiche"?
suitianshi,

2
@suitianshi: il documento standard POSIX 1003.1c elenca tutte le funzioni di 1003.1 rientranti (sicure da chiamare dai thread) e che non lo sono. Purtroppo non sono a conoscenza di una copia online gratuita disponibile ovunque.
Chris Dodd,

2
@ChrisDodd Ho trovato la copia su unix-systems.org/version4 e posso vedere l'elenco della tabella di interfaccia di sistema al capitolo 7.1 ma non vedo dove elenca le funzioni come operazioni atomiche. Non dubitare di te, ma puoi condividere / modificare la tua risposta per giustificare il tuo punto nel documento?
user153882,

17

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

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


4

Non vedo come ricevere in parallelo possa 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 messaggi non siano lunghi solo un byte, non è possibile far funzionare in modo affidabile nulla con la ricezione di più thread.

Gli invii multipli potrebbero funzionare se hai inviato l'intero messaggio in una singola chiamata, ma non ne sono sicuro. È possibile che uno possa sovrascriverne un altro. Certamente non ci sarebbe alcun vantaggio in termini di prestazioni nel farlo.

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


9
Se stai usando i socket SOCK_DGRAM, ogni recv riceverà un singolo datagramma; non sarà mai diviso tra recvs
Chris Dodd il

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

1
@Chris buon punto. Stavo assumendo TCP. @Jay Potresti chiarire la domanda "Possiamo chiamare send / recv in parallelo" suona come se volessi ricevere in parallelo.
Noah,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.