В данном случае клиент совсем не изменен по сравнению с листингами 8.3 и 8.4, а функция сервера main не изменилась по сравнению с листингом 8.1. Единственные внесенные изменения касаются функции dg_echo
, которая будет приведена в следующих четырех листингах. В листинге 25.1 [1] Все исходные коды программ, опубликованные в этой книге, вы можете найти по адресу http://www.piter.com.
представлены глобальные объявления.
Листинг 25.1. Глобальные объявления
//sigio/dgecho01.c
1 #include "unp.h"
2 static int sockfd;
3 #define QSIZE 8 /* размер входной очереди */
4 #define MAXDG 4096 /* максимальный размер дейтаграммы */
5 typedef struct {
6 void *dg_data; /* указатель на текущую дейтаграмму */
7 size_t dg_len; /* длина дейтаграммы */
8 struct sockaddr *dg_sa; /* указатель на sockaddr{} с адресом клиента */
9 socklen_t dg_salen; /* длина sockaddr{} */
10 } DG;
11 static DG dg[QSIZE]; /* очередь дейтаграмм для обработки */
12 static long cntread[QSIZE +1]; /* диагностический счетчик */
13 static int iget; /* следующий элемент для обработки в основном цикле */
14 static int iput; /* следующий элемент для считывания обработчиком
сигналов */
15 static int nqueue; /* количество дейтаграмм в очереди на обработку
в основном цикле */
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
Дескриптор сокета сохраняется в глобальной переменной, поскольку он необходим обработчику сигналов. Происходит инициализация очереди принятых дейтаграмм.
Читать дальше
Конец ознакомительного отрывка
Купить книгу