Читаем UNIX: разработка сетевых приложений полностью

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 устанавливает счетчик повторных передач в нуль.

Отправка дейтаграммы

45-47 Функция rtt_ts получает текущую отметку времени. Отметка времени хранится в структуре hdr, которая добавляется к данным пользователя. Одиночная дейтаграмма UDP отправляется функцией sendmsg. Функция rtt_start возвращает количество секунд для этого тайм-аута, а сигнал SIGALRM контролируется функцией alarm.

Установка буфера перехода
Перейти на страницу:

Все книги серии Мастер-класс

Секреты резьбы по дереву
Секреты резьбы по дереву

Изделия из древесины и материалов, имитирующих ее текстуру, привычным образом окружают нас в повседневной жизни, поэтому мы относимся к ней как к чему-то обыденному. Но как только ее коснется умелая рука мастера резьбы по дереву, рождается произведение искусства и раскрываются такие качества древесины, как богатая фактура, разнообразие цветов, особая теплота. Эта книга поможет читателю открыть для себя удивительный мир творчества и познать секреты резьбы по дереву. Автор надеется, что начинающие резчики найдут в ней интересный и полезный материал, который позволит им стать мастерами. В приложении представлены рисунки орнаментов и различных узоров, которые на первых порах можно копировать, а по мере приобретения навыка на их основе разрабатывать свои образцы.

Галина Алексеевна Серикова

Сделай сам / Хобби и ремесла / Руководства / Дом и досуг / Словари и Энциклопедии

Похожие книги