Почему этот сервер, который я написал, не обнаружил, что клиент закрыл для него сокет? - PullRequest
7 голосов
/ 12 ноября 2010

В клиенте у меня есть

close(sockfd)

где sockfd - это сокет, подключенный к серверу. На сервере я получил это:

if (sockfd.revents & POLLERR ||
    desc_set[i].revents & POLLHUP || desc_set[i].revents & POLLNVAL) { 
  close(sockfd.fd); 
  printf("Goodbye (connection closed)\n");
}

Где sockfd - это структура pollfd, а sockfd.fd - файловый дескриптор сокета клиента.

Когда клиент закрывает сокет, как я его положил, сервер, похоже, не обнаруживает его с помощью второго кода (desc_set [i] .revents & POLLHUP и т.

Кто-нибудь знает в чем проблема?

Ответы [ 2 ]

10 голосов
/ 12 ноября 2010

Похоже, вам удалось наполовину закрыть соединение со стороны клиента.В этом состоянии соединение все еще может отправлять данные в одном направлении, то есть оно работает в полудуплексном режиме.Это сделано специально и позволит вашему серверу завершить ответ на все отправленные клиентом сообщения.Как правило, это будет означать завершение передачи файла и вызов close(), или ответ на все аспекты запроса. В полузакрытом состоянии вы все еще вполне разумно можете отправлять данные на сторону, которая уже назвала close().На вашем сервере вы увидите eof, если попытаетесь прочитать хотя.close() просто означает «Я закончил отправку, завершите все, что я просил».

POLLHUP, POLLERR и POLLNVAL проверяет только выходную сторону локального соединения, которая по-прежнемудействует здесь.Существует POLLRDHUP, который является расширением GNU, который должен обнаруживать закрытие другой стороны, но тесты, которые вы выполняете, проверяют только, доступны ли они для записи, а не для чтения.

См. Также этот вопрос , который говорит о Java, но все еще очень связан.

4 голосов
/ 13 ноября 2010

Удаленное закрытие или отключение выхода не является ни ошибкой, ни зависанием, ни недопустимым состоянием. Это событие чтения такое, что read () вернет ноль. Просто обработайте это как часть вашей обычной обработки чтения.

КСТАТИ ваше тестовое условие должно читаться как sockfd.revents & (POLLERR | POLLHUP | POLLNVAL).

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