Вход/Регистрация
UNIX: разработка сетевых приложений
вернуться

Стивенс Уильям Ричард

Шрифт:

37 msgrecv.msg_iovlen = 2;

38 iovrecv[0].iov_base = &recvhdr;

39 iovrecv[0].iov_len = sizeof(struct hdr);

40 iovrecv[l].iov_base = inbuff;

41 iovrecv[l].iov_len = inbytes;

1-5
Мы включаем новый заголовочный файл
unprtt.h
, показанный в листинге 22.8, который определяет структуру
rtt_info
, содержащую информацию RTT для клиента. Мы определяем одну из этих структур и ряд других переменных.

Определение структур msghdr и структуры hdr

6-10
Мы хотим скрыть от вызывающего процесса добавление порядкового номера и отметки времени в начало каждого пакета. Проще всего использовать для этого функцию
writev
, записав свой заголовок (структура
hdr
), за которым следуют данные вызывающего процесса, в виде одной дейтаграммы UDP. Вспомните, что результатом выполнения функции
writev
на дейтаграммном сокете является отправка одной дейтаграммы. Это проще, чем заставлять вызывающий процесс выделять для нас место в начале буфера, а также быстрее, чем копировать наш заголовок и данные вызывающего процесса в один буфер (под который мы должны выделить память) для каждой функции
sendto
. Но поскольку мы работаем с UDP и нам необходимо задать адрес получателя, следует использовать возможности, предоставляемые структурой
iovec
функций
sendmsg
и
recvmsg
и отсутствующие в функциях
sendto
и
recvfrom
. Вспомните из раздела 14.5, что в некоторых системах доступна более новая структура
msghdr
, включающая вспомогательные данные (
msg_control
), тогда как в более старых системах вместо них применяются элементы
msg_accright
(так называемые права доступа — access rights), расположенные в конце структуры. Чтобы избежать усложнения кода директивами
#ifdef
для обработки этих различий, мы объявляем две структуры
msghdr
как
static
. При этом они инициализируются только нулевыми битами, а затем неиспользованные элементы в конце структур просто игнорируются.

Инициализация при первом вызове

20-24
При первом вызове нашей функции мы вызываем функцию
rtt_init
.

Заполнение структур msghdr

25-41
Мы заполняем две структуры
msghdr
, используемые для ввода и вывода. Для данного пакета мы увеличиваем на единицу порядковый номер отправки, но не устанавливаем отметку времени отправки, пока пакет не будет отправлен (поскольку он может отправляться повторно, а для каждой повторной передачи требуется текущая отметка времени).

Вторая часть функции вместе с обработчиком сигнала

sig_alarm
показана в листинге 22.7.

Листинг 22.7. Функция dg_send_recv: вторая половина

//rtt/dg_send_rеcv.c

42 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 void

66 sig_alrm(int signo)

67 {

68 siglongjmp(jmpbuf, 1);

69 }

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

42-43
Для сигнала
SIGALRM
устанавливается обработчик сигналов, а функция
rtt_newpack
устанавливает счетчик повторных передач в нуль.

Отправка дейтаграммы
  • Читать дальше
  • 1
  • ...
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

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