Чтение онлайн

на главную - закладки

Жанры

UNIX: разработка сетевых приложений
Шрифт:
ПРИМЕЧАНИЕ

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);

17 servaddr.sin_port = htons(SERV_PORT);

18 Bind(listenfd, (SA*)&servaddr, sizeof(servaddr));

19 Listen(listenfd, LISTENQ);

20 client[0].fd = listenfd;

21 client[0].events = POLLRDNORM;

22 for (i = 1; i < OPEN_MAX; i++)

23 client[i].fd = -1; /* -1
означает, что элемент свободен */

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) { /* новое соединение

с клиентом */

28 clilen = sizeof(cliaddr);

29 connfd = Accept(listenfd. (SA*)&cliaddr, &clilen);

30 for (i = 1; i < OPEN_MAX; i++)

31 if (client[1].fd < 0) {

32 client[i].fd = connfd; /* сохраняем дескриптор */

33 break;

34 }

35 if (i == OPEN_MAX)

36 err_quit("too many clients");

37 client[i].events = POLLRDNORM;

38 if (i > maxi)

39 maxi = i; /* максимальный индекс в массиве client[] */

40 if (--nready <= 0)

Поделиться:
Популярные книги

Решала

Иванов Дмитрий
10. Девяностые
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Решала

Все не случайно

Юнина Наталья
Любовные романы:
современные любовные романы
7.10
рейтинг книги
Все не случайно

Око василиска

Кас Маркус
2. Артефактор
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Око василиска

Неудержимый. Книга XIV

Боярский Андрей
14. Неудержимый
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Неудержимый. Книга XIV

Жребий некроманта 3

Решетов Евгений Валерьевич
3. Жребий некроманта
Фантастика:
боевая фантастика
5.56
рейтинг книги
Жребий некроманта 3

Делегат

Астахов Евгений Евгеньевич
6. Сопряжение
Фантастика:
боевая фантастика
постапокалипсис
рпг
5.00
рейтинг книги
Делегат

Запасная дочь

Зика Натаэль
Фантастика:
фэнтези
6.40
рейтинг книги
Запасная дочь

Real-Rpg. Еретик

Жгулёв Пётр Николаевич
2. Real-Rpg
Фантастика:
фэнтези
8.19
рейтинг книги
Real-Rpg. Еретик

Восход. Солнцев. Книга VI

Скабер Артемий
6. Голос Бога
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Восход. Солнцев. Книга VI

Действуй, дядя Доктор!

Юнина Наталья
Любовные романы:
короткие любовные романы
6.83
рейтинг книги
Действуй, дядя Доктор!

Авиатор: назад в СССР 12

Дорин Михаил
12. Покоряя небо
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Авиатор: назад в СССР 12

Адепт. Том 1. Обучение

Бубела Олег Николаевич
6. Совсем не герой
Фантастика:
фэнтези
9.27
рейтинг книги
Адепт. Том 1. Обучение

Земная жена на экспорт

Шах Ольга
Любовные романы:
любовно-фантастические романы
5.57
рейтинг книги
Земная жена на экспорт

Варлорд

Астахов Евгений Евгеньевич
3. Сопряжение
Фантастика:
боевая фантастика
постапокалипсис
рпг
5.00
рейтинг книги
Варлорд