6.11. Эхо-сервер TCP (еще раз)

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)

41     continue; /* больше нет дескрипторов, готовых для чтения */

42   }

43   for (i = 1; i <= maxi; i++) { /* проверяем все клиенты на наличие

                                      данных */

44    if ((sockfd = client[i].fd) < 0)

45     continue;

46    if (client[i].revents & (POLLRDNORM | POLLERR)) {

47     if ((n = Read(sockfd, buf, MAXLINE)) < 0) {

48      if (errno == ECONNRESET) {

49       /* соединение переустановлено клиентом */

50       Close(sockfd);

51       client[i].fd = -1;

52      } else

53       err_sys("readline error");

54     } else if (n == 0) {

55      /* соединение закрыто клиентом */

56      Close(sockfd);

57      client[i].fd = -1;

58     } else

59      Writen(sockfd, line, n);

60     if (--nready <= 0)

61      break; /* больше нет дескрипторов, готовых для чтения */

62    }

63   }

64  }

65 }

Вызов функции poll, проверка нового соединения

26-42 Мы вызываем функцию poll для ожидания нового соединения либо данных на существующем соединении. Когда новое соединение принято, мы находим первый свободный элемент в массиве client — это первый элемент с отрицательным дескриптором. Обратите внимание, что мы начинаем поиск с индекса 1, поскольку элемент client[0] используется для прослушиваемого сокета. Когда свободный элемент найден, мы сохраняем дескриптор и устанавливаем событие POLLRDNORM.

Проверка данных на существующем соединении

43-63 Два события, которые нас интересуют, — это POLLRDNORM и POLLERR. Второй флаг в элементе event мы не устанавливали, поскольку этот флаг возвращается всегда, если соответствующее условие выполнено. Причина, по которой мы проверяем событие POLLERR, в том, что некоторые реализации возвращают это событие, когда приходит сегмент RST, другие же в такой ситуации возвращают событие POLLRDNORM. В любом случае мы вызываем функцию read, и если произошла ошибка, эта функция возвратит ее. Когда существующее соединение завершается клиентом, мы просто присваиваем элементу fd значение -1.

Поделитесь на страничке

Следующая глава >

Похожие главы из других книг

FTP-сервер

Из книги Asterisk™: будущее телефонии Второе издание автора Меггелен Джим Ван

FTP-сервер В настоящее время мы предпочитаем использовать для конфигурации аппаратов Polycom протокол FTP (File Transfer Protocol - протокол передачи файлов)1. Мы бы рекомендовали выбрать его, а не TFTP и для устройств, которые могут работать с обоими протоколами. В системе CentOS при


Сервер INN

Из книги Сетевые средства Linux автора Смит Родерик В.

Сервер INN Среди серверов новостей, предназначенных для выполнения в системе Linux, наиболее популярным является InterNetNews, или INN (http://www.isc.org/products/INN). Пакет INN состоит из нескольких программ, работающих совместно. Основная программа, innd, предназначена для обработки новых статей


Web-сервер

Из книги HTML 5, CSS 3 и Web 2.0. Разработка современных Web-сайтов. автора Дронов Владимир

Web-сервер Когда мы тестировали нашу первую Web-страницу, то прекрасно обошлись без Web-сервера, открыв ее прямо в Web-обозревателе. Но в дальнейшем, особенно когда мы начнем реализовывать подгрузку содержимого, Web-сервер все-таки нам понадобится. Многие Web-сценарии нормально


Web-сервер

Из книги HTML 5, CSS 3 и Web 2.0. Разработка современных Web-сайтов автора Дронов Владимир

Web-сервер Когда мы тестировали нашу первую Web-страницу, то прекрасно обошлись без Web-сервера, открыв ее прямо в Web-обозревателе. Но в дальнейшем, особенно когда мы начнем реализовывать подгрузку содержимого, Web-сервер все-таки нам понадобится. Многие Web-сценарии нормально


Сервер

Из книги Интернет – легко и просто! автора Александров Егор

Сервер Сервером называют постоянно работающий компьютер, подключенный к Сети. Если вернуться к нашему парку развлечений, то сервер – это один из его аттракционов. Помимо основных функций хранения и передачи информации, сервер может являться входом в Интернет для


Выделенный сервер

Из книги Бесплатные разговоры через Интернет автора Фрузоров Сергей

Выделенный сервер Под словосочетанием «выделенный сервер» понимается обыкновенный сервер, то есть компьютер, постоянно подключенный к Интернету и сконфигурированный для работы в нем. Слово «выделенный» подчеркивает, что этот сервер ни от кого не зависит и находится в


Конфигурируем сервер

Из книги Ubuntu 10. Краткое руководство пользователя автора Колисниченко Д. Н.

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


26.2. Web-сервер

Из книги Введение в QNX/Neutrino 2. Руководство по программированию приложений реального времени в QNX Realtime Platform автора Кёртен Роб

26.2. Web-сервер 26.2.1. Установка Apache и PHP Запустите менеджер Synaptic. В поле Быстрый поиск введите apache. Щелкните правой кнопкой мыши на пакете apache2 и выберите команду Отметить для установки. Менеджер пакетов сообщит вам, что нужно установить дополнительные пакеты (рис. 26.1). Нажмите


Сервер

Из книги Недокументированные и малоизвестные возможности Windows XP автора Клименко Роман Александрович

Сервер Теперь, когда мы рассмотрели клиента, перейдем к серверу. Клиент использовал функцию ConnectAttach() для создания соединения с сервером, а затем использовал функцию MsgSend() для передачи сообщений.Создание каналаПод этим подразумевается, что сервер должен создать канал —


Сервер

Из книги Linux глазами хакера автора Флёнов Михаил Евгеньевич

Сервер С помощью данной службы обеспечивается общий доступ к файлам, принтерам и именованным каналам данного компьютера. Иными словами, если данная служба будет отключена, то на компьютере нельзя будет создавать общедоступные ресурсы, а сетевые компьютеры не смогут


Глава 7 Web-сервер

Из книги Мир InterBase. Архитектура, администрирование и разработка приложений баз данных в InterBase/FireBird/Yaffil автора Ковязин Алексей Николаевич

Глава 7 Web-сервер Несмотря на то, что изначально сеть создавалась для обмена файлами, с появлением первого браузера популярность WWW-страниц начала расти не по дням, а по часам. Сейчас уже трудно себе представить не только Интернет, но и интранет без Web-страниц.Для того чтобы


Глава 11 DNS-сервер

Из книги Программирование для Linux. Профессиональный подход автора Митчелл Марк

Глава 11 DNS-сервер Каждый компьютер, подключенный к сети, должен иметь свой адрес, чтобы его легко можно было найти и обмениваться с ним данными. Это как телефонные аппараты. Чтобы кому-нибудь позвонить, нужно знать его номер телефона, иначе коммутатор не сможет понять, с кем


Сервер для InterBase

Из книги Анонимность и безопасность в Интернете. От «чайника» к пользователю автора Колисниченко Денис Николаевич

Сервер для InterBase Рассмотрим компоненты сервера согласно традиционным описаниям конфигурации компьютеров: платформа, процессор, материнская плата, ОЗУ, жесткие диски, сетевую платуПлатформа. Под платформой понимается архитектура процессора, например Intel. Большинство


11.2.3. Сервер

Из книги UNIX: разработка сетевых приложений автора Стивенс Уильям Ричард


1.3.1. Прокси-сервер – что это?

Из книги автора

1.3.1. Прокси-сервер – что это? Итак, что такое прокси-сервер? Это узел сети, служащий для кэширования информации и ограничения доступа в сеть. Прокси-серверы устанавливаются как администраторами локальной сети для нужд ее самой, так и провайдерами Интернета для нужд всех их


6.11. Эхо-сервер TCP (еще раз)

Из книги автора

6.11. Эхо-сервер TCP (еще раз) Теперь мы изменим наш эхо-сервер TCP из раздела 6.8, используя вместо функции select функцию poll. В предыдущей версии сервера, работая с функцией select, мы должны были выделять массив client вместе с набором дескрипторов rset (см. рис. 6.12). С помощью функции poll мы