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

на главную - закладки

Жанры

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

16 struct udpiphdr *ui;

17 Signal(SIGALRM, sig_alrm);

18 if (sigsetjmp(jmpbuf, 1)) {

19 if (nsent >= 3)

20 err_quit("no response");

21 printf("timeout\n");

22 timeout *= 2; /* геометрическая прогрессия: 3, 6, 12 */

23 }

24 canjump = 1; /* siglongjmp разрешен */

25 send_dns_query;

26 nsent++;

27 alarm(timeout);

28 ui = udp_read;

29 canjump = 0;

30 alarm(0);

31 if (ui->ui_sum == 0)

32 printf("UDP checksums off\n");

33 else

34 printf("UDP checksums on\n");

35 if (verbose)

36 printf("received UDP checksum = %x\n", ntohs(ui->ui_sum));

37 }

Переменные volatile

15
Нам нужно, чтобы две динамические локальные переменные
nsent
и
timeout
сохраняли свои значения после возвращения
siglongjmp
из обработчика сигнала в нашу функцию. Реализация допускает восстановление значений динамических локальных переменных, предшествовавших вызову функции
sigsetjump
[110, с. 178], но добавление спецификатора
volatile
предотвращает это восстановление.

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

15-16
Для сигнала
SIGALRM
устанавливается обработчик сигнала, а функция
sigsetjmp
устанавливает буфер перехода для функции
siglongjmp
. (Эти две функции подробно описаны в разделе 10.15 [110].) Значение 1 во втором аргументе функции
sigsetjmp
указывает, что требуется сохранить текущую маску сигнала, так как мы будем вызывать функцию
siglongjmp
из нашего обработчика сигнала.

Функция siglongjmp

19-23
Этот фрагмент кода выполняется, только когда функция
siglongjmp
вызывается из нашего обработчика сигнала. Вызов указывает на возникновение условий, при которых мы входим в состояние ожидания: мы отправили запрос, на который не пришло никакого ответа. Если после того, как мы отправим три запроса, ответа не будет, мы прекращаем выполнение кода. По истечении времени ожидания, отведенного на получение ответа, мы выводим соответствующее сообщение и увеличиваем значение времени ожидания в два раза, то есть задаем экспоненциальное смещение( exponential backoff), которое также описано в разделе 20.5. Первое значение времени ожидания равно 3 с, затем — 6 с и 12 с.

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

sigsetjmp
и
siglongjmp
, вместо того чтобы
просто перехватывать ошибку
EINTR
(как мы поступили в листинге 14.1), заключается в том, что библиотечные функции захвата пакетов (которые вызываются из нашей функции
udp_read
) заново запускают операцию чтения в случае возвращения ошибки
EINTR
. Поскольку мы не хотим модифицировать библиотечные функции, единственным решением для нас является перехватывание сигнала
SIGALRM
и выполнение нелокального перехода (оператора
goto
), который возвращает управление в наш код, а не в библиотечную функцию.

Отправка запроса DNS и считывание ответа

25-26
Функция
send_dns_query
(см. листинг 29.8) отправляет запрос DNS на сервер имен. Функция
dns_read
считывает ответ. Мы вызываем функцию
alarm
для предотвращения «вечной» блокировки функции
read
. Если истекает заданное (в секундах) время ожидания, генерируется сигнал
SIGALRM
, и наш обработчик сигнала вызывает функцию
siglongjmp
.

Анализ полученной контрольной суммы UDP

27-32
Если значение полученной контрольной суммы UDP равно нулю, это значит, что сервер не вычислил и не отправил контрольную сумму.

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

sig_alrm
— обработчик сигнала
SIGALRM
.

Листинг 29.7. Функция sig_alrm: обработка сигнала SIGALRM

//udpcksum/udpcksum.c

1 #include "udpcksum.h"

2 #include <setjmp.h>

3 static sigjmp_buf jmpbuf;

4 static int canjump;

5 void

6 sig_alrm(int signo)

7 {

8 if (canjump == 0)

9 return;

10 siglongjmp(jmpbuf, 1);

11 }

8-10
Флаг
canjump
был установлен в листинге 29.6 после инициализации буфера перехода функцией
sigsetjmp
. Если флаг был установлен, в результате вызова функции
siglongjmp
управление осуществляется таким образом, как если бы функция
sigsetjmp
из листинга 29.6 возвратила бы значение 1.

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

send_dns_query
, посылающая запрос UDP на сервер DNS. Эта функция формирует запрос DNS.

Листинг 29.8. Функция send_dns_query: отправка запроса UDP на сервер DNS

//udpcksum/senddnsquery-raw.c

6 void

7 send_dns_query(void)

8 {

9 size_t nbytes;

10 char *buf, *ptr;

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

Свадьба по приказу, или Моя непокорная княжна

Чернованова Валерия Михайловна
Любовные романы:
любовно-фантастические романы
5.57
рейтинг книги
Свадьба по приказу, или Моя непокорная княжна

Сборник коротких эротических рассказов

Коллектив авторов
Любовные романы:
эро литература
love action
7.25
рейтинг книги
Сборник коротких эротических рассказов

Отец моего жениха

Салах Алайна
Любовные романы:
современные любовные романы
7.79
рейтинг книги
Отец моего жениха

Вадбольский

Никитин Юрий Александрович
1. Вадбольский
Фантастика:
попаданцы
5.00
рейтинг книги
Вадбольский

Бастард Императора. Том 7

Орлов Андрей Юрьевич
7. Бастард Императора
Фантастика:
городское фэнтези
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Бастард Императора. Том 7

Повелитель механического легиона. Том VIII

Лисицин Евгений
8. Повелитель механического легиона
Фантастика:
технофэнтези
аниме
фэнтези
5.00
рейтинг книги
Повелитель механического легиона. Том VIII

В зоне особого внимания

Иванов Дмитрий
12. Девяностые
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
В зоне особого внимания

Таня Гроттер и магический контрабас

Емец Дмитрий Александрович
1. Таня Гроттер
Фантастика:
фэнтези
8.52
рейтинг книги
Таня Гроттер и магический контрабас

Бастард Императора. Том 2

Орлов Андрей Юрьевич
2. Бастард Императора
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Бастард Императора. Том 2

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

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

Третий

INDIGO
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
Третий

Возвышение Меркурия. Книга 16

Кронос Александр
16. Меркурий
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Возвышение Меркурия. Книга 16

Идеальный мир для Лекаря 9

Сапфир Олег
9. Лекарь
Фантастика:
боевая фантастика
юмористическое фэнтези
6.00
рейтинг книги
Идеальный мир для Лекаря 9

Потусторонний. Книга 1

Погуляй Юрий Александрович
1. Господин Артемьев
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Потусторонний. Книга 1