сокет: постоянно получая POLLHUP на полузакрытых - PullRequest
2 голосов
/ 07 июля 2011

Я написал сокет-сервер, работающий на linux, но, вероятно, это не спецификация linux.

Я использую poll() для проверки состояния клиентов.Мои клиенты делают активное (наполовину) закрытие после отправки запроса.Сервер постоянно получает POLLHUP и POLLERR из-за полузакрытия клиента.Я также вижу POLLRDHUP, так что я знаю, что на самом деле это полузакрытие, а не закрытие / сброс соединения.Моя проблема в том, что я всегда получаю эти события, даже несмотря на то, что я уже знал из предыдущего опроса, что была половина закрытия.

Как я могу отключить это, чтобы я больше не получал это событие?Я пытался сделать дополнительные read() и сделать shutdown(fd, SHUT_RD), но, похоже, это не помогло.Я не хочу, чтобы poll проснулся от события, которое я уже обработал.

Ответы [ 2 ]

3 голосов
/ 08 июля 2011

Прекратите включать fd в набор readfds, как только вы наполовину закроете. Больше нечего читать , кроме полузакрытых. С этой точки зрения единственное, что вас может заинтересовать - это «доступные для записи» события.

0 голосов
/ 10 сентября 2013

Просто игнорируйте POLLHUP в ответных флагах. Существующий код, если он правильный, будет делать то, что вы хотите.

Тот факт, что вы продолжите получать полузакрытия от poll() (обрисовано в общих чертах в ответе EJP), является функцией, а не ошибкой. Это позволяет вам обращаться с полузакрытыми точно так же, как конец файла; это именно то, что вы хотите, так как оно позволяет вашему приложению читать последние байты в буфере сокета, а не отбрасывать их (что является правильной семантикой полузакрытия TCP).

Как только достигается "обычный" конец файла, poll() всегда выбирает дескриптор файла как готовый для чтения. Затем предполагается, что цикл вокруг poll() будет read() данных до конца файла, а затем close(). Игнорирование условия POLLHUP позволяет вашей программе делать то же самое с тем же кодом в полузакрытых ситуациях и получать последние байты в буфере сокета.

Аналогично, вы должны реализовать поток управления, не заботясь о POLLHUP. Если (и только если ) вам необходимо ограничить дескриптор файла (т. Е. В настоящее время некуда поместить байты read()), то удалите этот дескриптор из набора poll(), чтобы ядро не даст вам готовых к прочтению "прерываний", пока вы не скажете это снова (без регулирования). Тот факт, что все данные уже находятся в буфере сокета (что указывает бит POLLHUP), снова не имеет значения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...