Z podręcznika epoll_ctl:Biorąc pod uwagę każde zdarzenie gniazda TCP epoll, jeśli EPOLLRDHUP = 0 i EPOLLIN = 1; to jest kolejne wywołanie read()/recv() gwarantowane, aby zwrócić rozmiar odczytu nie równy 0?
EPOLLRDHUP (od wersji Linuksa 2.6.17)
Stream wzajemnej gniazdo zamknięte połączenie lub wyłączyć pisanie połowę połączenia. (Flaga ta jest szczególnie przydatna do pisania prosty kod do wykrywania wzajemnej wyłączenie przy użyciu wyzwalany zboczem monitoringu.)
Z podręcznika recv:
Jeśli żadne komunikaty są dostępne do pobrania oraz peer występował procedurę zamykania, recv() zwraca 0.
wydaje mi się więc, że oba powyższe pokrywy te same scenariusze, i że tak długo, jak złapać wydarzenia EPOLLRDHUP pierwszy, ja nigdy nie powinny otrzymują read() lub recv() o długości 0 (a więc nie potrzebują t o sprawdzać takie). Ale czy to jest zagwarantowane?
"Być może FIN przybywa po tym, jak otrzymałeś EPOLLIN = 1, ale zanim zadzwonisz recv()." Ale nawet jeśli FIN pojawi się w takiej chwili, recv() zwróci coś większego niż 0, prawda? Ponieważ rura FIFO nadal zawiera cokolwiek wywołaną EPOLLIN = 1. – Will
Świetna odpowiedź. Zmieniłbym go tak, by powiedział: "... czytaj dalej, ale powinieneś być przygotowany na to, że recv() nadal będzie zwracał 0 ** lub -1 **, na wszelki wypadek". – selbie
@selbie Oczywiście powinienem zrobić i sprawdzić -1 (zarówno dla EAGAIN, jak i różnych nagłych błędów). Ponadto, mimo że procedura opisana w tej odpowiedzi może być najlepsza i najbezpieczniejsza (i robię to dokładnie w moim bieżącym kodzie), to * nie * jest świetną odpowiedzią, ponieważ nie daje satysfakcjonującej odpowiedzi na * dlaczego * Muszę sprawdzić na 0 (w wyżej wspomnianym scenariuszu). – Will