2012-01-03 14 views
9

Si supponga che un socket TCP sull'host Linux locale sia in uno stato connesso con un host remoto. L'host locale sta utilizzando epoll_wait per ricevere una notifica degli eventi sul socket con l'host remoto.Epoll e arresto a 1 via remoto

Se l'host remoto dovesse chiamare:

shutdown(s,SHUT_WR); 

sul suo socket connesso per indicare che è fatto trasmettere, quale evento (s) sarà epoll_wait ritorno sull'host locale per la sua presa di corrente?

Suppongo che EPOLLIN venga sempre restituito e una chiamata recv successiva restituisca 0 per indicare che il lato remoto ha terminato la trasmissione.

Che dire di EPOLLHUP o EPOLLRDHUP? (E qual è la differenza tra questi due eventi)?

O addirittura EPOLLERR?

Se l'host remoto chiama "close" anziché "shutdown", la risposta a una delle modifiche precedenti?

risposta

18

Sto rispondendo a me stesso dopo aver fatto il lavoro pesante per trovare la risposta.

Una presa ascolto per eventi epoll tipicamente riceverà un EPOLLRDHUP (oltre a EPOLLIN) condizione evento sul peer remoto chiamando vicino o arresto (SHUT_WR). Questo non significa necessariamente che la presa è morta. Le chiamate successive a recv() restituiranno tutti i dati non letti sul socket e alla fine verrà restituito "0" per indicare EOF. Potrebbe anche essere possibile inviare i dati indietro se il peer remoto ha fatto solo una mezza chiusura del suo socket.

L'unica eccezione notevole è se il peer remoto sta utilizzando l'opzione SO_LINGER abilitata sul suo socket con un valore di "0". Il risultato della chiusura di un socket potrebbe causare l'invio di un RST TCP anziché un FIN. Da quello che ho letto, un evento di reset della connessione genererà un EPOLLHUP o EPOLLERR. (Non ho avuto il tempo di confermare, ma ha senso).

Alcuni documenti suggeriscono che esistono implementazioni Linux meno recenti che non supportano EPOLLRDHUP, in quanto invece viene generato EPOLLHUP.

E per quello che vale, nel mio caso particolare, ho scoperto che non è troppo interessante avere codice in casi speciali di eventi EPOLLHUP o EPOLLRDHUP. Invece, considera questi eventi come EPOLLIN/EPOLLOUT e chiama recv() (o send() come appropriato). Ma prestate molta attenzione ai codici restituiti restituiti da recv() e send().

+1

Ho avuto altre domande sul comportamento qui, quindi ho effettuato un'immersione dettagliata in queste interazioni: https://medium.com/where-the-flamingcow-roams/down-the-epoll-rabbit-hole-5c0447cb6329 – flamingcow

Problemi correlati