C ++, как использовать выбор, чтобы увидеть, если сокет закрыт - PullRequest
18 голосов
/ 12 апреля 2011

Может ли кто-нибудь предоставить мне пример того, как использовать select (), чтобы увидеть, закрыл ли клиент соединение через сокет?

FYI. Я использую Linux.

Спасибо!

Ответы [ 4 ]

21 голосов
/ 12 апреля 2011

Приведенный ниже фрагмент сначала проверяет, помечен ли сокет как читаемый (каковым он является при закрытии), а затем проверяет, есть ли что-нибудь для чтения.

#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/ioctl.h>

bool isclosed(int sock) {
  fd_set rfd;
  FD_ZERO(&rfd);
  FD_SET(sock, &rfd);
  timeval tv = { 0 };
  select(sock+1, &rfd, 0, 0, &tv);
  if (!FD_ISSET(sock, &rfd))
    return false;
  int n = 0;
  ioctl(sock, FIONREAD, &n);
  return n == 0;
}
8 голосов
/ 08 июля 2014

Вам не нужно делать select() с последующим ioctl(). Вместо этого вы можете выполнить неблокирующий просмотр сокета, чтобы увидеть, вернется ли он 0.

bool isclosed (int sock) {
    char x;
interrupted:
    ssize_t r = ::recv(sock, &x, 1, MSG_DONTWAIT|MSG_PEEK);
    if (r < 0) {
        switch (errno) {
        case EINTR:     goto interrupted;
        case EAGAIN:    break; /* empty rx queue */
        case ETIMEDOUT: break; /* recv timeout */
        case ENOTCONN:  break; /* not connected yet */
        default:        throw(errno);
        }
    }
    return r == 0;
}
4 голосов
/ 12 апреля 2011

Если вы получили уведомление о прочтении, и чтение вернуло 0 байтов, клиент завершил работу корректно. Если нет, вы получите уведомление об исключении.

1 голос
/ 12 апреля 2011

Если клиент закрылся корректно, вы должны получить уведомление о том, что READ не будет блокироваться и помечено ИСКЛЮЧЕНИЕ (третий набор).

Если клиент неудачно закрылся, вы не знаете.Это связано с проблемой двух генералов.

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