неблокирующая tcp связь с epoll - PullRequest
5 голосов
/ 20 мая 2010

Мое приложение linux выполняет неблокирующий системный вызов TCP connect, а затем использует epoll_wait для обнаружения завершения трехстороннего рукопожатия. Иногда epoll_wait возвращается с обоими POLLOUT & POLLERR событиями, установленными для одного и того же дескриптора сокета.

Я хотел бы понять, что происходит на уровне TCP. Я не могу воспроизвести это по требованию. Я предполагаю, что между двумя вызовами epoll_wait внутри моего цикла событий у нас была последовательность SYN + ACK / ACK / FIN, но, опять же, я не могу ее воспроизвести.

Ответы [ 2 ]

6 голосов
/ 21 мая 2010

Вполне вероятно, что это произойдет, если не удалось установить соединение - например, с «тайм-аутом соединения» (для сокетов, выполняющих неблокирующее соединение, POLLOUT устанавливается, когда операция соединения завершена как для успешной, так и для неудачной попытки результаты).

Когда для сокета устанавливается POLLOUT, используйте getsockopt(sock, SOL_SOCKET, SO_ERROR, ...), чтобы проверить, успешно ли установлено соединение (в этом случае опция сокета SO_ERROR равна 0, и в противном случае указывает, почему не удалось установить соединение).

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

Вот хорошая информация о неблокирующем tcp connect () .

При обнаружении ошибки сокета (то есть соединение закрыто / отказано / время ожидания), epoll возвращает зарегистрированные события интереса POLLIN / POLLOUT с POLLERR. Поэтому epoll_wait () вернет POLLOUT | POLLERR, если вы зарегистрировали POLLOUT, или POLLIN | POLLOUT | POLLERR, если POLLIN | POLLOUT был зарегистрирован.

То, что epoll возвращает POLLIN, не означает, что будут доступны данные для чтения, поскольку recv () может просто вернуть ошибку из неблокирующего вызова connect (). Я думаю, epoll возвращает все зарегистрированные события с помощью POLLERR, чтобы программа вызывала send () / recv () / etc .. и получала ошибку сокета. Некоторые программы никогда не проверяют наличие POLLERR / POLLHUP и только перехватывают ошибки сокетов при следующем вызове send () / recv ().

...