2015-02-20 10 views
7

Voglio essere in grado di chiamare recv() senza dover bloccare, quindi voglio renderlo non bloccante, ma non voglio che non blocchi durante l'invio di dati. Quindi una presa può essere resa non bloccante solo per la funzione recv() oppure la modalità di blocco/non blocco influisce su tutte le funzioni del socket?Un socket può essere reso non bloccante solo per la funzione recv()?

+1

È possibile utilizzare il flag 'MSG_PEEK' per vedere se c'è qualcosa da ricevere. Oppure usa per es. 'select' con un timeout zero. Tuttavia, per i socket TCP questi metodi funzionano solo per dire che c'è un leas * un * byte da ricevere, non si sa quanto è realmente disponibile. –

+2

Sì, ma l'ultima volta che ho controllato recv() non bloccherà se c'è anche 1 byte di dati. – Joshua

+1

@Joachim Pileborg Ma anche se avessi usato 'MSG_PEEK',' recv() 'avrebbe comunque bloccato. –

risposta

0

Non è possibile rendere il socket non bloccante solo per la funzione recv().

Tuttavia c'è qualcosa di simile (ma difettoso), che è utilizzando ioctlsocket() con il flag FIONREAD. Per esempio:

unsigned long l; 
ioctlsocket(s, FIONREAD, &l); 

Questa funzione restituisce (immediatamente senza bloccare) quanti byte è disponibile per essere letto, anche se non è abbastanza preciso (ma non ci preoccupiamo di questo, perché stiamo usando per sapere se ci sono dati da leggere e non sapere esattamente quanti byte ci sono).

Come ho già accennato in precedenza, questo approccio è viziata, perché non ti dice quando l'altra estremità è disconnesso, perché recv() rendimenti 0 sulla disconnessione, e questa funzione ritornerà 0 se non sono disponibili dati!

2

Per Windows, è possibile utilizzare ioctlsocket() per impostare il socket in modalità non bloccante. Sfortunatamente queste impostazioni si applicano a tutte le operazioni sul socket. Quindi per il tuo caso dovrai passare tra le ricezioni e le spedizioni.

Per la cronaca: Per Linux, si potrebbe avere usato la bandiera MSG_DONTWAIT nelle recv() argomenti di chiamata. La singola chiamata sarà quindi non bloccante.

+1

Quale non è portatile in quanto non è una bandiera standard. Ad esempio, non è disponibile nella libreria winsock di Windows. –

+0

@JoachimPileborg Sì! Colpa mia: non ho notato il tag di Windows. Ho modificato la mia risposta. – Christophe

+0

Non posso farlo solo: 'unsigned long l; ioctlsocket (s, FIONREAD, &l); 'per vedere se ci sono dati da leggere? –

Problemi correlati