Значение аргумента timeout | Описание |
---|---|
INFTIM | Ждать вечно |
0 | Возвращать управление немедленно, без блокирования |
>0 | Ждать в течение указанного числа миллисекунд |
Константа
INFTIM
определена как отрицательное значение. Если таймер в данной системе не обеспечивает точность порядка миллисекунд, значение округляется в большую сторону до ближайшего поддерживаемого значения.
POSIX требует, чтобы константа INFTIM была определена в заголовочном файле
Как и в случае функции select, любой тайм-аут, установленный для функции poll, ограничивается снизу разрешающей способностью часов в конкретной реализации (обычно 10 мс).
Функция
poll
возвращает -1, если произошла ошибка, 0 — если нет готовых дескрипторов до истечения времени таймера, иначе возвращается число дескрипторов с ненулевым элементом
revents
.
Если нас больше не интересует конкретный дескриптор, достаточно установить элемент
fd
структуры
pollfd
равным отрицательному значению. В этом случае элемент
events
будет проигнорирован, а элемент
revents
при возвращении функции будет сброшен в нуль.
Вспомните наши рассуждения в конце раздела 6.3 относительно константы
FD_SETSIZE
и максимального числа дескрипторов в наборе в сравнении с максимальным числом дескрипторов для процесса. У нас не возникает подобных проблем с функцией
poll
, поскольку вызывающий процесс отвечает за размещение массива структур
pollfd
в памяти и за последующее сообщение ядру числа элементов в массиве. Не существует типа данных фиксированного размера, аналогичного
fd_set
, о котором знает ядро.
POSIX требует наличия и функции select, и функции poll. Но если сравнивать их с точки зрения переносимости, то функцию select в настоящее время поддерживает больше систем, чем функцию poll. POSIX определяет также функцию pselect — усовершенствованную версию функции select, которая обеспечивает возможность блокирования сигналов и предоставляет лучшую разрешающую способность по времени, а для функции poll ничего подобного в POSIX нет.
6.11. Эхо-сервер TCP (еще раз)
Теперь мы изменим наш эхо-сервер TCP из раздела 6.8, используя вместо функции
select
функцию
poll
. В предыдущей версии сервера, работая с функцией
select
, мы должны были выделять массив
client
вместе с набором дескрипторов
rset
(см. рис. 6.12). С помощью функции
poll
мы разместим в памяти массив структур
pollfd
. В нем же мы будем хранить и информацию о клиенте, не создавая для нее другой массив. Элемент
fd
этого массива мы обрабатываем тем же способом, которым обрабатывали массив
client
(см. рис. 6.12): значение -1 говорит о том, что элемент не используется, а любое другое значение является номером дескриптора. Вспомните из предыдущего раздела, что любой элемент в массиве структур
pollfd
, передаваемый функции
poll
с отрицательным значением элемента
fd
, просто игнорируется.
В листинге 6.5 показана первая часть кода нашего сервера.
Листинг 6.5. Первая часть сервера TCP, использующего функцию poll
//tcpcliserv/tcpservpoll01.с
1 #include "unp.h"
2 #include <1imits.h> /* для OPEN_MAX */
3 int
4 main(int argc, char **argv)
5 {
6 int i, maxi, listenfd, connfd, sockfd;
7 int nready;
8 ssize_t n;
9 char buf[MAXLINE];
10 socklen_t clilen;
11 struct pollfd client[OPEN_MAX];
12 struct sockaddr_in cliaddr, servaddr;
13 listenfd = Socket(AF_INET, SOCK_STREAM, 0);
14 bzero(&servaddr, sizeof(servaddr));
15 servaddr.sin_family = AF_INET;
16 servaddr.sin_addr.s_addr = htonl(INADDR_ANY);