Чтобы сделать неблокирующий connect(), предполагая, что сокет уже сделан неблокирующим:
int res = connect(fd, ...);
if (res < 0 && errno != EINPROGRESS) {
// error, fail somehow, close socket
return;
}
if (res == 0) {
// connection has succeeded immediately
} else {
// connection attempt is in progress
}
Во втором случае, когда connect() завершился с ошибкой EINPROGRESS (и только в этом случае), вам нужно дождаться, пока сокет станет доступным для записи, например. для epoll укажите, что вы ожидаете EPOLLOUT на этом сокете. Как только вы получите уведомление о том, что он доступен для записи (с epoll также ожидается получение события EPOLLERR или EPOLLHUP), проверьте результат попытки подключения:
int result;
socklen_t result_len = sizeof(result);
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &result, &result_len) < 0) {
// error, fail somehow, close socket
return;
}
if (result != 0) {
// connection failed; error code is in 'result'
return;
}
// socket is ready for read()/write()
По моему опыту, в Linux функция connect() никогда не срабатывает сразу, и вам всегда приходится ждать возможности записи. Однако, например, во FreeBSD я видел, как неблокирующий метод connect() с локальным хостом срабатывал сразу.
person
Ambroz Bizjak
schedule
17.04.2012
dup
иclose
дескриптор (и использовать дубликат). Не проверял, но должно работать, как я понимаю. В документах указано, что не проверять возвращаемое значениеclose
является серьезной ошибкой программирования, поскольку это может вернуть предыдущую ошибку. Это именно то, что вам нужно (еслиclose
выдает ошибку,connect
не удалось). Хотя, конечно, если вы используетеepoll
, то у вас гарантированно будет ОС, гдеgetsockopt(SO_ERROR)
будет просто работать... - person Damon   schedule 17.04.2012getattrinfo_a
тоже делает это внутри). Таким образом, хотя вы все равно блокируете работника, вы также можете блокировать его при подключении... - person Damon   schedule 17.04.2012