Это архив сайта coldflame.by.ru, он не обновлялся с 2007 года. Мой современный сайт тут: http://leonid.shevtsov.me.
Домой! Обо мне Специально для РИ-06-1 Разнообразное... барахло, короче :) Программы и прочее Статьи и переводы Блог SmartDaemon
Предыдущая ОглавлениеСледующая

select()

Проверить, готовы ли дескрипторы к приему/передаче

Прототипы

#include <sys/select.h>

int select(int n, fd_set *readfds, fd_set *writefds,
           fd_set *exceptfds, struct timeval *timeout);
FD_SET(int fd, fd_set *set);
FD_CLR(int fd, fd_set *set);
FD_ISSET(int fd, fd_set *set);
FD_ZERO(fd_set *set);

Описание

Функция select() дает возможность одновременно проверять несколько сокетов на наличие входящих данных, возможность отправки данных, и на исключения.

Сначала ты наполняешь наборы дескрипторов, используя макросы, вроде FD_SET() Когда набор готов, ты передаешь его в функцию одним из параметров: readfds, если хочешь проверить, готовы ли сокеты (один из сокетов) к приему, writefds, чтобы проверить, готов ли один из сокетов в передаче, или exceptfds, если хочешь узнать, произошло ли исключение (ошибка) на одном из сокетов. Любой параметр (или все) могут быть равны NULL, если определенный тип события тебя не интересует. После вызова select() изменяет наборы, чтобы отразить проихошедшие события: каждый набор содержит сокеты. готовые соответственно к приему, передаче или вызвали исключение.

Первый параметр, n, самый большой дескриптор из всех наборов (ведь дескрипторы - просто целые числа), плюс один.

timeout указывает, сколько будт ждать select(). Она завершится либо по окончанию таймаута, либо при событии. struct timeval имеет два поля: таймаут равен tv_sec - количеству секунд, плюс tv_usec - количество микросекунд (в 1 секунде 1,000,000 микросекунд.

Макросы выполняют такие действия:

FD_SET(int fd, fd_set *set);

Добавляет fd в набор set.

FD_CLR(int fd, fd_set *set);

Удаляет fd из набора set.

FD_ISSET(int fd, fd_set *set);

Возвращает true, если fd принадлежит набору set.

FD_ZERO(fd_set *set);

Очистить набор set.

Возвращаемое значение

Возвращает общее количество дескрипторов, 0, если функция завершилась по таймауту, или -1 при ошибке, сохраняя ее номер в errno. После вызова наборы содержат только готовые сокеты.

Пример

int s1, s2, n;
fd_set readfds;
struct timeval tv;
char buf1[256], buf2[256];

s1 = socket(PF_INET, SOCK_STREAM, 0);
s2 = socket(PF_INET, SOCK_STREAM, 0);

// здесь мы соединяемся с серверами
//connect(s1, ...)...
//connect(s2, ...)...

// очищаем набор
FD_ZERO(&readfds);

// добавляем в набор
FD_SET(s1, &readfds);
FD_SET(s2, &readfds);

// поскольку мы получили s2 позже, он больше, чем s1,
// тогда параметр n равен
n = s2 + 1;

// ждем входящих данных (таймаут 10.5 секунд)
tv.tv_sec = 10;
tv.tv_usec = 500000;
rv = select(n, &readfds, NULL, NULL, &tv);

if (rv == -1) {
    perror("select"); // ошибка в select()
} else if (rv == 0) {
    printf("Таймаут! За 10.5 секунд данные не поступали.\n");
} else {
    // один или более дескрипторов готовы к чтению
    if (FD_ISSET(s1, &readfds)) {
        recv(s1, buf1, sizeof(buf1), 0);
    }
    if (FD_ISSET(s2, &readfds)) {
        recv(s1, buf2, sizeof(buf2), 0);
    }
}

См. также

poll()


Предыдущая ОглавлениеСледующая