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

на главную

Жанры

UNIX: разработка сетевых приложений
Шрифт:

16 static socklen_t clilen; /* максимальная длина sockaddr{} */

17 static void sig_io(int);

18 static void sig_hup(int);

Очередь принимаемых дейтаграмм

3-12
Обработчик сигнала
SIGIO
помещает приходящие дейтаграммы в очередь. Эта очередь является массивом структур
DG
, который интерпретируется как кольцевой буфер. Каждая структура содержит указатель на принятую дейтаграмму, ее длину и указатель на структуру адреса сокета, содержащую адрес протокола клиента и размер адреса протокола. В памяти размещается столько этих структур, сколько указано в
QSIZE
данном случае 8), и в листинге 25.2 будет видно, что функция
dg_echo
для размещения в памяти всех структур дейтаграмм и адресов сокетов вызывает функцию
malloc
. Также происходит выделение памяти под диагностический счетчик
cntread
, который будет рассмотрен чуть ниже. На рис. 25.2 приведен массив структур, при этом предполагается, что первый элемент указывает на 150-байтовую дейтаграмму, а длина связанного с ней адреса сокета равна 16.

Рис. 25.2. Структуры данных, используемые для хранения прибывающих дейтаграмм и структур адресов их сокетов

Индексы массивов

13-15
Переменная
iget
является индексом следующего элемента массива для обработки в основном цикле, а переменная
iput
— это индекс следующего элемента массива, в котором сохраняется результат действия обработчика сигнала. Переменная
nqueue
обозначает полное количество дейтаграмм, предназначенных для обработки в основном цикле.

В листинге 25.2 показан основной цикл сервера — функция

dg_echo
.

Листинг 25.2. Функция dg_echo: основной обрабатывающий цикл сервера

//sigio/dgecho01.c

19 void

20 dg_echo(int sockfd_arg, SA *pcliaddr, socklen_t clilen_arg)

21 {

22 int i;

23 const int on = 1;

24 sigset_t zeromask, newmask, oldmask;

25 sockfd = sockfd_arg;

26 clilen = clilen_arg;

27 for (i = 0; i < QSIZE; i++) { /* инициализация очереди */

28 dg[i].dg_data = Malloc(MAXDG);

29 dg[i].dg_sa = Malloc(clilen);

30 dg[i].dg_salen = clilen;

31 }

32 iget = iput = nqueue = 0;

33 Signal(SIGHUP, sig_hup);

34 Signal(SIGIO, sig_io);

35 Fcntl(sockfd, F_SETOWN, getpid);

36 Ioctl(sockfd, FIOASYNC, &on);

37 Ioctl(sockfd. FIONBIO, &on);

38 Sigemptyset(&zeromask); /* инициализация трех наборов сигналов */

39 Sigemptyset(&oldmask);

40 Sigemptyset(&newmask);

41 Sigaddset(&newmask, SIGIO); /* сигнал, который хотим блокировать*/

42 Sigprocmask(SIG_BLOCK, &newmask, &oldmask);

43 for (;;) {

44 while (nqueue == 0)

45 sigsuspend(&zeromask); /* ждем дейтаграмму для обработки */

46 /* разблокирование SIGIO */

47 Sigprocmask(SIG_SETMASK, &oldmask, NULL);

48 Sendto(sockfd, dg[iget].dg_data, dg[iget].dg_len, 0,

49 dg[iget].dg_sa, dg[iget].dg_salen);

50 if (++iget >= QSIZE)

51 iget = 0;

52 /*
блокировка SIGIO */

53 Sigprocmask(SIG_BLOCK, &newmask, &oldmask);

54 nqueue--;

55 }

56 }

Инициализация очереди принятых дейтаграмм

27-32
Дескриптор сокета сохраняется в глобальной переменной, поскольку он необходим обработчику сигналов. Происходит инициализация очереди принятых дейтаграмм.

Установка обработчиков сигналов и флагов сокетов

33-37
Для сигналов
SIGHUP
(он используется для диагностических целей) и
SIGIO
устанавливаются обработчики. С помощью функции
fcntl
задается владелец сокета, а с помощью функции
ioctl
устанавливаются флаги ввода-вывода, управляемого сигналом, и неблокируемого ввода-вывода.

ПРИМЕЧАНИЕ

Ранее отмечалось, что для разрешения ввода-вывода, управляемого сигналом, в POSIX применяется флаг O_ASYNC функции fcntl, но поскольку большинство систем пока его не поддерживают, мы используем функцию ioctl. Поскольку большинство систем не поддерживают флаг O_NONBLOCK для включения неблокируемого ввода-вывода, здесь также рассмотрен вариант использования функции ioctl.

Инициализация наборов сигналов

38-41
Инициализируется три набора сигналов:
zeromask
(никогда не изменяется),
oldmask
(хранит старую маску сигнала, когда
SIGIO
блокируется) и
newmask
. Функция
sigaddset
включает в набор
newmask
бит, соответствующий
SIGIO
.

Блокирование SIGIO и ожидание дальнейших действий

42-45
Функция
sigprocmask
сохраняет текущую маску сигналов процесса в
oldmask
, а затем выполняет логическое сложение, сравнивая
newmask
с текущей маской сигналов. Такие действия блокируют сигнал
SIGIO
и возвращают текущую маску сигналов. Далее мы заходим в цикл
for
и проверяем счетчик
nqueue
. Пока этот счетчик равен нулю, ничего делать не нужно, и мы вызываем функцию
sigsuspend
. Эта функция POSIX, сохранив в одной из локальных переменных текущую маску сигналов, присваивает текущей маске значение аргумента
zeromask
. Так как
zeromask
является пустым набором сигналов, то разрешается доставка любых сигналов. Как только перехватывается сигнал и завершается обработчик, функция
sigsuspend
также завершается. (Это необычная функция, поскольку она всегда возвращает ошибку
EINTR
.) Прежде чем завершиться, функция
sigsuspend
всегда устанавливает такое значение маски сигналов, которое предшествовало ее вызову (в данном случае
newmask
). Таким образом гарантируется, что, когда функция
sigsuspend
возвращает значение, сигнал
SIGIO
блокирован. Именно поэтому можно проверять счетчик
nqueue
, поскольку известно, что пока он проверяется, сигнал
SIGIO
не может быть доставлен.

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

Я все еще граф. Книга IX

Дрейк Сириус
9. Дорогой барон!
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Я все еще граф. Книга IX

Кодекс Крови. Книга VIII

Борзых М.
8. РОС: Кодекс Крови
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Крови. Книга VIII

Огненный князь

Машуков Тимур
1. Багряный восход
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Огненный князь

Ученичество. Книга 1

Понарошку Евгений
1. Государственный маг
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Ученичество. Книга 1

Деспот

Шагаева Наталья
Любовные романы:
современные любовные романы
эро литература
5.00
рейтинг книги
Деспот

Инцел на службе демоницы 1 и 2: Секса будет много

Блум М.
Инцел на службе демоницы
Фантастика:
фэнтези
5.25
рейтинг книги
Инцел на службе демоницы 1 и 2: Секса будет много

Тринадцатый

NikL
1. Видящий смерть
Фантастика:
фэнтези
попаданцы
аниме
6.80
рейтинг книги
Тринадцатый

Кодекс Охотника. Книга XIII

Винокуров Юрий
13. Кодекс Охотника
Фантастика:
боевая фантастика
попаданцы
аниме
7.50
рейтинг книги
Кодекс Охотника. Книга XIII

Чехов. Книга 3

Гоблин (MeXXanik)
3. Адвокат Чехов
Фантастика:
альтернативная история
5.00
рейтинг книги
Чехов. Книга 3

Изменить нельзя простить

Томченко Анна
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Изменить нельзя простить

Сирота

Ланцов Михаил Алексеевич
1. Помещик
Фантастика:
альтернативная история
5.71
рейтинг книги
Сирота

Делегат

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

Эйгор. В потёмках

Кронос Александр
1. Эйгор
Фантастика:
боевая фантастика
7.00
рейтинг книги
Эйгор. В потёмках

Наследник с Меткой Охотника

Тарс Элиан
1. Десять Принцев Российской Империи
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Наследник с Меткой Охотника