Скачиваний:
90
Добавлен:
12.05.2015
Размер:
913.92 Кб
Скачать

13.8. Последовательные и параллельные серверы

Сервер в нашем простом примере из предыдущего раздела являлся последовательным сервером (iterative server). Он последовательно обрабатывал запросы клиентов, переходя к следующему только после полного завершения работы с предыдущим. Например, если два клиента пошлют запрос такому серверу приблизительно одновременно, причем один из них запросит 10-мегабайтный файл, отправка которого займет, например, 10 секунд, а второй – 10-байтный файл, то второму придется ждать, по меньшей мере, 10 секунд, пока не будет обслужен первый клиент.

Альтернативой является параллельный сервер (concurrent server). Наиболее часто встречаемый в Unix вид такого сервера называют one-child-per-client (каждому клиенту – один дочерний процесс). Сервер вызывает функцию fork для создания дочернего процесса каждый раз, когда появляется новый клиент. Дочерний процесс полностью обрабатывает запрос клиента, а поддержка многозадачности в Unix обеспечивает параллельность выполнения всех этих процессов. Однако существуют и другие методы решения этой задачи, подробно описанные в разделе 27.5 (глава 5):

  • создание пула дочерних процессов и передача нового клиента свободному дочернему процессу;

  • создание одного программного потока для каждого клиента;

  • создание пула потоков и передача нового клиента свободному потоку.

Хотя в главе 5 обсуждаются проблемы создания сетевых серверов, те же методы применимы и к серверам межпроцессного взаимодействия (IPC server), клиенты которых находятся на одном узле с сервером.

Атака типа “отказ в обслуживании”. Один из недостатков последовательных серверов был уже отмечен выше – некоторым клиентам приходится ждать дольше, чем нужно, потому что их запросы приходят после запросов других клиентов, запрашивающих большие файлы. Существует и другая проблема. Вспомним наш пример с интерпретатором команд, приведенный после листинга 13.7, и относящееся к нему обсуждение того, что сервер блокируется при вызове функции open для открытия FIFO клиента, если клиент еще не открыл его (чего не происходит до выполнения команды cat). Это дает возможность злоумышленнику “подвесить” сервер, послав ему запрос без последующего открытия FIFO клиента. Этот тип атаки называется “отказ в обслуживании” (Denial of Service – DoS). Чтобы исключить возможность такой атаки, нужно быть аккуратным при написании последовательной части программного кода любого сервера, учитывая возможность и потенциальную продолжительность его блокирования. Одним из методов решения проблемы является установка максимального времени ожидания для некоторых операций, однако обычно проще сделать сервер параллельным, а не последовательным, поскольку в этом случае атака будет воздействовать лишь на один из дочерних процессов, а не на весь сервер. Однако даже параллельный сервер не защищен от атаки полностью: злоумышленник все еще может послать множество запросов, что приведет к превышению предела количества порожденных сервером дочерних процессов и невозможности выполнения последующих вызовов функции fork.

13.9. Ограничения программных каналов и fifo

На программные каналы и FIFO системой накладывается всего два ограничения:

  1. OPEN_MAX – максимальное количество дескрипторов, которые могут быть одновременно открыты некоторым процессом (в ОС Linux – 1024).

  2. PIPE_BUF – максимальный объем данных, для которого гарантируется атомарность операции записи (в ОС Linux – 4096 байт).

Значения обеих переменных можно получить с помощью команды getconf.

Соседние файлы в папке Chapter.4