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
24 maxi = 0; /* максимальный индекс массива client[] */
Размещение массива структур pollfd в памяти
11
Мы объявляем массив структур
pollfd
размером
OPEN_MAX
. Не существует простого способа определить максимальное число дескрипторов, которые могут быть открыты процессом. Мы снова столкнемся с этой проблемой в листинге 13.1. Один из способов ее решения — вызвать функцию POSIX
sysconf
с аргументом
_SC_OPEN_MAX
[110, с. 42-44], а затем динамически выделять в памяти место для массива соответствующего размера. Однако функция
sysconf
может возвратить некое «неопределенное» значение, и в этом случае нам придется задавать ограничение самим. Здесь мы используем только константу
OPEN_MAX
стандарта POSIX.
Инициализация
20-24
Мы используем первый элемент в массиве
client
для прослушиваемого сокета и присваиваем дескрипторам для оставшихся элементов -1. Мы также задаем в качестве аргумента функции
poll
событие
POLLRDNORM
, чтобы получить уведомление от этой функции в том случае, когда новое соединение будет готово к приему. Переменная
maxi
содержит максимальный индекс массива
client
, используемый в настоящий момент.
Вторая часть нашей функции приведена в листинге 6.6.
Листинг 6.6. Вторая часть сервера TCP, использующего функцию poll
//tcpcliserv/tcpservpoll01.c
25 for (;;) {
26 nready = Poll(client, maxi + 1, INFTIM);
27 if (client[0].revents & POLLRDNORM) { /* новое соединение