UNIX: разработка сетевых приложений, стр. 250
Инициализация при первом вызове
20-24rtt_initЗаполнение структур msghdr
25-41msghdrВторая часть функции вместе с обработчиком сигнала
sig_alarmЛистинг 22.7. Функция dg_send_recv: вторая половина
//rtt/dg_send_rеcv.c42 Signal(SIGALRM, sig_alrm);43 rtt_newpack(&rttinfo); /* инициализируем для этого пакета */44 sendagain:45 sendhdr.ts = rtt_ts(&rttinfo);46 Sendmsg(fd, &msgsend, 0);47 alarm(rtt_start(&rttinfo)); /* вычисляем тайм-аут. запускаем таймер */48 if (sigsetjmp(jmpbuf, 1) != 0) {49 if (rtt_timeout(&rttinfо) < 0) {50 err_msg("dg_send_recv: no response from server, giving up");51 rttinit = 0; /* повторная инициализация для следующего вызова */52 errno = ETIMEDOUT;53 return (-1);54 }55 goto sendagain;56 }57 do {58 n = Recvmsg(fd, &msgrecv, 0);59 } while (n < sizeof(struct hdr) || recvhdr.seq != sendhdr.seq);60 alarm(0); /* останавливаем таймер SIGALRM */61 /* вычисляем и записываем новое значение оценки RTT */62 rtt_stop(&rttinfo, rtt_ts(&rttinfo) — recvhdr.ts);63 return (n - sizeof(struct hdr)); /* возвращаем размер полученной дейтаграммы */64 }65 static void66 sig_alrm(int signo)67 {68 siglongjmp(jmpbuf, 1);69 }Установка обработчика сигналов
42-43SIGALRMrtt_newpackОтправка дейтаграммы
45-47rtt_tshdrsendmsgrtt_startSIGALRMalarmУстановка буфера перехода
48recvmsgsigsetjmpsiglongjmpSIGALRMsigsetjmpОбработка тайм-аута
49-55rtt_timeouterrnoETIMEDOUTВызов функции recvmsg, сравнение порядковых номеров
57-59recvmsghdrrecvmsgВыключение таймера и обновление показателей RTT
60-62alarmrtt_stoprtt_tsОбработчик сигнала SIGALRM
65-69siglongjmpsigsetjmpdg_send_recvТеперь мы рассмотрим различные функции RTT, которые вызывались нашей функцией
dg_send_recvunprtt.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 {