UNIX: разработка сетевых приложений
UNIX: разработка сетевых приложений читать книгу онлайн
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
Мы не уменьшаем значение переменной
maxiЭтот сервер сложнее, чем сервер, показанный в листингах 5.1 и 5.2, но он позволяет избежать затрат на создание нового процесса для каждого клиента, что является хорошим примером использования функции
selectacceptАтака типа «отказ в обслуживании»
К сожалению, функционирование только что описанного сервера вызывает проблемы. Посмотрим, что произойдет, если некий клиент-злоумышленник соединится с сервером, отправит 1 байт данных (отличный от разделителя строк) и войдет в состояние ожидания. Сервер вызовет функцию
readlinereadДело в том, что обрабатывая множество клиентов, сервер никогда не должен блокироваться в вызове функции, относящейся к одному клиенту. В противном можно «подвесить» сервер, что приведет к отказу в обслуживании для всех остальных клиентов. Это называется атакой типа «отказ в обслуживании» (DoS attack — Denial of Service). Такая атака воздействует на сервер, делая невозможным обслуживание нормальных клиентов. Обезопасить себя от подобных атак позволяют следующие решения: использовать неблокируемый ввод-вывод (см. главу 16), предоставлять каждому клиенту обслуживание отдельным потоком (например, для каждого клиента порождать процесс или поток) или установить тайм-аут для ввода-вывода (см. раздел 14.2).
6.9. Функция pselect
Функция
pselect#include <sys/select.h>#include <signal.h>#include <time.h>int pselect(int <i>maxfdp1</i>, fd_set *<i>readset</i>, fd_set *<i>writeset</i>, fd_set *<i>exceptset</i>, const struct timespec *<i>timeout</i>, const sigset_t *<i>sigmask</i>);<i>Возвращает: количество готовых дескрипторов, 0 в случае тайм-аута, -1 в случае ошибки</i>Функция
pselectselect1. Функция
pselecttimespectimevalstruct timespec { time_t tv_sec; /* секунды */ long tv_nsec; /* наносекунды */};Эти структуры отличаются вторыми элементами: элемент
tv_nsectv_usec2. В функции
pselectpselectВ отношении второго пункта рассмотрим следующий пример (описанный на с. 308–309 [110]). Обработчик сигнала нашей программы для сигнала
SIGINTintr_flagerrnoEINTRselectif (intr_flag) handle_intr(); /* обработка этого сигнала */if ((nready = select(...)) < 0) { if (errno == EINTR) { if (intr_flag) handle_intr(); } ...}Проблема заключается в том, что если сигнал придет в промежутке между проверкой переменной
intr_flagselectselectpselectsigset_t newmask, oldmask, zeromask;sigemptyset(&zeromask);sigemptyset(&newmask);sigaddset(&newmask, SIGINT);sigprocmask(SIG_BLOCK, &newmask, &oldmask); /* блокирование сигнала SIGINT */if (intr_flag) handle_intr(); /* обработка этого сигнала */if ((nready = pselect(..., &zeromask)) < 0) { if (errno == EINTR) { if (intr_flag) handle_intr(); } ...}Перед проверкой переменной
intr_flagSIGINTpselectzeromaskpselectpselectSIGINT
