UNIX: разработка сетевых приложений
Шрифт:
64 }
65 static void
66 sig_alrm(int signo)
67 {
68 siglongjmp(jmpbuf, 1);
69 }
Установка обработчика сигналов
42-43
Для сигнала SIGALRM
устанавливается обработчик сигналов, а функция rtt_newpack
устанавливает счетчик повторных передач в нуль. Отправка
дейтаграммы
45-47
Функция rtt_ts
получает текущую отметку времени. Отметка времени хранится в структуре hdr
, которая добавляется к данным пользователя. Одиночная дейтаграмма UDP отправляется функцией sendmsg
. Функция rtt_start
возвращает количество секунд для этого тайм-аута, а сигнал SIGALRM
контролируется функцией alarm
. Установка буфера перехода
48
Мы устанавливаем буфер перехода для нашего обработчика сигналов с помощью функции sigsetjmp. Мы ждем прихода следующей дейтаграммы, вызывая функцию recvmsg
. (Совместное использование функций sigsetjmp
и siglongjmp
вместе с сигналом SIGALRM
мы обсуждали применительно к листингу 20.5.) Если время таймера истекает, функция sigsetjmp
возвращает 1. Обработка тайм-аута
49-55
Когда возникает тайм-аут, функция rtt_timeout
вычисляет следующее значение RTO (используя экспоненциальное смещение) и возвращает -1, если нужно прекратить попытки передачи дейтаграммы, или 0, если нужно выполнить очередную повторную передачу. Когда мы прекращаем попытки, мы присваиваем переменной errno
значение ETIMEDOUT
и возвращаемся в вызывающую функцию. Вызов функции recvmsg, сравнение порядковых номеров
57-59
Мы ждем прихода дейтаграммы, вызывая функцию recvmsg
. Длина полученной дейтаграммы не должна быть меньше размера структуры hdr
, а ее порядковый номер должен совпадать с порядковым номером запроса, ответом на который предположительно является эта дейтаграмма. Если при сравнении хотя бы одно из этих условий не выполняется, функция recvmsg
вызывается снова. Выключение таймера и обновление показателей RTT
60-62
Когда приходит ожидаемый ответ, функция alarm
отключается, а функция rtt_stop
обновляет оценочное значение RTT. Функция rtt_ts
возвращает текущую отметку времени, и отметка времени из полученной дейтаграммы вычитается из текущей отметки, что дает в результате RTT. Обработчик сигнала SIGALRM
65-69
Вызывается функция siglongjmp
, результатом выполнения которой является то, что функция sigsetjmp
в dg_send_recv
возвращает 1. Теперь
мы рассмотрим различные функции RTT, которые вызывались нашей функциейdg_send_recv
. В листинге 22.8 показан заголовочный файл unprtt.h
. Листинг 22.8. Заголовочный файл unprtt.h
//lib/unprtt.h
1 #ifndef __unp_rtt_h
2 #define __unp_rtt_h
3 #include "unp.h"
4 struct rtt_info {
5 float rtt_rtt; /* последнее измеренное значение RTT в секундах */
6 float rtt_srtt; /* сглаженная оценка RTT в секундах */
7 float rtt_rttvar; /* сглаженные средние значения отклонений
в секундах */
8 float rtt_rto; /* текущее используемое значение RTO, в секундах */
9 int rtt_nrexmt; /* количество повторных передач: 0, 1, 2, ... */
10 uint32_t rtt_base; /* число секунд, прошедшее после 1.1.1970 в начале */
11 };
12 #define RTT_RXTMIN 2 /* минимальное значение тайм-аута для
повторной передачи, в секундах */
13 #define RTT_RXTMAX 60 /* максимальное значение тайм-аута для
повторной передачи, в секундах */
14 #define RTT_MAXNREXMT 3 /* максимально допустимое количество
повторных передач одной дейтаграммы */
15 /* прототипы функций */
16 void rtt_debug(struct rtt_info*);
17 void rtt_init(struct rtt_info*);
18 void rtt_newpack(struct rtt_info*);
19 int rtt_start(struct rtt_info*);
20 void rtt_stop(struct rtt_info*, uint32_t);
21 int rtt_timeout(struct rtt_info*);
22 uint32_t rtt_ts(struct rtt_info*);
23 extern int rtt_d_flag; /* может быть ненулевым при наличии
дополнительной информации */
24 #endif /* _unp_rtt_h */
Структура rtt_info
4-11
Эта структура содержит переменные, необходимые для того, чтобы определить время передачи пакетов между клиентом и сервером. Первые четыре переменных взяты из уравнений, приведенных в начале этого раздела.
12-14
Эти константы определяют минимальный и максимальный тайм-ауты повторной передачи и максимальное число возможных повторных передач. В листинге 22.9 показан макрос
RTT_RTOCALC
и первые две из четырех функций RTT.
Поделиться с друзьями: