Вход/Регистрация
UNIX: разработка сетевых приложений
вернуться

Стивенс Уильям Ричард

Шрифт:

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

Тем не менее у нас имеется область, в которой желательно применение именно последовательного сервера — это сравнение характеристик других серверов. Если мы запустим клиент следующим образом:

% client 192.168.1.20 8888 1 5000 4000

и соединимся с последовательным сервером, то получим такое же количество соединений TCP (5000) и такое же количество данных, передаваемых по одному соединению. Но поскольку сервер является последовательным, на нем не осуществляется никакого управления процессами. Это дает нам возможность получить базовое значение времени, затрачиваемого центральным процессором на обработку указанного количества запросов, которое потом мы можем вычесть из результатов измерений для других серверов. С точки зрения управления процессами последовательный сервер является самым быстрым, поскольку он вовсе не занимается этим управлением. Взяв последовательный сервер за точку отсчета, мы можем сравнивать результаты измерений быстродействия других серверов, показанные в табл. 30.1.

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

30.5. Параллельный сервер TCP: один дочерний процесс для каждого клиента

Традиционно параллельный сервер TCP вызывает функцию

fork
для порождения нового дочернего процесса, который будет выполнять обработку очередного клиентского запроса. Это позволяет серверу обрабатывать несколько запросов одновременно, выделяя по одному дочернему процессу для каждого клиента. Единственным ограничением на количество одновременно обрабатываемых клиентских запросов является ограничение операционной системы на количество дочерних процессов, допустимое для пользователя, в сеансе которого работает сервер. Листинг 5.9 содержит пример параллельного сервера, и большинство серверов TCP написаны в том же стиле.

Проблема с параллельными серверами заключается в количестве времени, которое тратит центральный процессор на выполнение функции

fork
для порождения нового дочернего процесса для каждого клиента. Давным-давно, в конце 80-х годов XX века, когда наиболее загруженные серверы обрабатывали сотни или тысячи клиентов за день, это было приемлемо. Но расширение Сети изменило требования. Теперь загруженными считаются серверы, обрабатывающие миллионы соединений TCP в день. Сказанное относится лишь к одиночным узлам, но наиболее загруженные сайты используют несколько узлов, распределяя нагрузку между ними (в разделе 14.2 [112] рассказывается об общепринятом способе распределения этой нагрузки, называемом циклическим обслуживанием DNS — DNS round robin). В последующих разделах описаны различные способы, позволяющие избежать вызова функции
fork
для каждого клиентского запроса, но тем не менее параллельные серверы остаются широко распространенными.

В листинге 30.2 показана функция

main
для нашего параллельного сервера TCP.

Листинг 30.2. Функция main для параллельного сервера TCP

//server/serv01.c

1 include "unp.h"

2 int

3 main(int argc, char **argv)

4 {

5 int listenfd, connfd;

6 pid_t childpid;

7 void sig_chld(int), sig_int(int), web_child(int);

8 socklen_t clilen, addrlen;

9 struct sockaddr *cliaddr;

10 if (argc == 2)

11 listenfd = Tcp_listen(NULL, argv[1], &addrlen);

12 else if (argc == 3)

13 listenfd = Tcp_listen(argv[1], argv[2], &addrlen);

14 else

15 err_quit("usage: serv01 [ <host> ] <port#>");

16 cliaddr = Malloc(addrlen);

17 Signal(SIGCHLD, sig_chld);

18 Signal(SIGINT, sig_int);

19 for (;;) {

20 clilen = addrlen;

21 if ((connfd = accept(listenfd, cliaddr, &clilen)) < 0) {

22 if (errno == EINTR)

23 continue; /* назад к for */

24 else

25 err_sys("accept error");

26 }

27 if ((childpid = Fork) == 0) { /* дочерний процесс */

28 Close(listenfd); /* закрываем прослушиваемый сокет */

29 web_child(connfd); /* обрабатываем запрос */

  • Читать дальше
  • 1
  • ...
  • 432
  • 433
  • 434
  • 435
  • 436
  • 437
  • 438
  • 439
  • 440
  • 441
  • 442
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

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