время ожидания подключения к сокету в c с помощью poll - PullRequest
2 голосов
/ 22 сентября 2011

У меня есть существующее многопоточное приложение, которое использует блокирующий вызов connect ().

Однако я хочу ввести время ожидания подключения для приложения, когда, если сервер не ответит на наш запрос в течение x миллисекунд, приложение прекратит попытки и выдаст ошибку.

Однако я не могувыяснить, как сделать это с помощью опроса.

@ caf неблокирующее соединение с использованием select очень помогло. Но я читал, что select медленнее по сравнению с опросом, поэтому я хочу использовать опрос.Не могли бы вы сказать мне, если это правда?

Я вставляю его код из сообщения здесь

int main(int argc, char **argv) {
u_short port;                /* user specified port number */
char *addr;                  /* will be a pointer to the address */
struct sockaddr_in address;  /* the libc network address data structure */
short int sock = -1;         /* file descriptor for the network socket */
fd_set fdset;
struct timeval tv;

if (argc != 3) {
    fprintf(stderr, "Usage %s <port_num> <address>\n", argv[0]);
    return EXIT_FAILURE;
}

port = atoi(argv[1]);
addr = argv[2];

address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr(addr); /* assign the address */
address.sin_port = htons(port);            /* translate int2port num */

sock = socket(AF_INET, SOCK_STREAM, 0);
fcntl(sock, F_SETFL, O_NONBLOCK);

connect(sock, (struct sockaddr *)&address, sizeof(address));

FD_ZERO(&fdset);
FD_SET(sock, &fdset);
tv.tv_sec = 10;             /* 10 second timeout */
tv.tv_usec = 0;

if (select(sock + 1, NULL, &fdset, NULL, &tv) == 1)
{
    int so_error;
    socklen_t len = sizeof so_error;

    getsockopt(sock, SOL_SOCKET, SO_ERROR, &so_error, &len);

    if (so_error == 0) {
        printf("%s:%d is open\n", addr, port);
    }
}

close(sock);
return 0;

}

Не могли бы вы помочь мне написать аналогичный функционал с помощью опроса.

Я нахожусь на RHEL и использую версию gcc 4.5.x.

Обновление: для текущего кода как изменить сокет в режим блокировки, как только приложение создает соединения с сервером.Я не могу найти способ снять этот O_NONBLOCK. Обновление 2: fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL) & ~O_NONBLOCK); В одном сообщении указано, что мы можем сделать это с помощью приведенной выше команды.Хотя не получил логин.

Ответы [ 2 ]

4 голосов
/ 22 сентября 2011

Производительность select () и poll () по отношению к другим системно-зависимым API опроса эквивалентна, если опрашивается только несколько файловых дескрипторов.Они оба плохо масштабируются, но могут работать очень хорошо, когда программа прослушивает только несколько fds.

Преимущество других API-интерфейсов опроса, специфичных для системы, состоит в том, что они выдвигают связанное состояние в ядро, так что каждыйДля опроса syscall не требуется копировать состояние из пространства пользователя в пространство ядра.Только с несколькими событиями эти издержки копирования и сканирования незначительны, и это преимущество не существует.

Просто придерживайтесь select (), если вам не нужно масштабировать до обработки сотен или более fds.

Если вы действительно будете работать со многими fds и должны поддерживать как Linux, так и Solaris, рассмотрите возможность использования библиотеки, такой как libevent или libev , для абстрагирования от специфичных для ядра эффективных API ожидания.

0 голосов
/ 22 сентября 2011

select не будет медленнее, чем опрос.Но даже если бы это было так, маловероятно, что минимальное различие будет иметь значение в вашем приложении.

Для выполнения неблокирующего подключения по таймауту вы можете скопировать из существующих приложений, которые предоставляют такую ​​функциональность.(см., например, здесь , чтобы узнать, как это сделать).

...