Мультиплексирование ввода/вывода в сокетах

Рейтинг: 1Ответов: 1Опубликовано: 11.05.2011

Написал такой кусочек кода:

struct pollfd fds[1];
fds[0].fd = intf->fd;
fds[0].events = POLLIN|POLLOUT;
rc = poll(fds, 1, timeout);
// произошло событие
if(rc > 0){
    if(fds[0].revents&(POLLERR|POLLHUP)){
        rc = ErrorHandling;
    }
    else if(fds[0].revents&POLLIN){
        // прием данных
        if((intf->RXBufCSize == 0) || (intf->RXBufCSize < BufCap)){
            rc = Receiving;
        }
        else{
            rc = WaitingIO;
        }
    }
    else if(fds[0].revents&(POLLOUT)){
        // передача данных
        if(intf->TXBufCSize > 0){
            rc = Transmiting;
        }
        else{
            rc = WaitingIO;
        }
    }
}
else{
    // таймаут вышел
    if(rc == 0){
        rc = WaitingIO;
    }
    else{
        rc = ErrorHandling;
    }
}

При разрыве соединения не возникает события POLLHUP, узнать о нем я могу только с помощью 0 который возвращает функция recv(). А так хочется с помощью poll() узнавать о разрыве. В чем может быть проблема?

Ответы

▲ 4Принят

0 на recv - это событие EOF, означающее "Читать уже нечего". Но ничего не говорит о возможности записи.

HUP - это разрыв соединения, означающее "Писать уже без толку". Но ничего не говорит о возможности чтения (в системном буфере возможно есть что считать).

Если сторона A вызовет shutdown(s, SHUT_WR), то на стороне B должен случится EOF. Если сторона A вызовет close(s), то по идее у B должен случиться HUP. Но протокол tcp не позволяет определить - close там был вызван или shutdown.

HUP на стороне B можно получить в таких случаях:

  1. Заранее сделать на стороне B shutdown(s, SHUT_WR) и работать только на чтение. Когда сторона A закроет соединение, на B случится HUP, т.к. закрыты оба канала tcp-соединения.

  2. У unix-сокетов такой проблемы нет. Сторона B сразу узнает о close(s) стороны A (т.е. случается HUP).

  3. При ошибке на tcp-сокете, несовместимой с жизнью сокета. Случается ERR и HUP одновременно.

  4. При ошибке неблокирующего connect(s,...). Соединения не было вообще, но все равно случается HUP.

  5. ... наверняка еще есть случаи.