-->

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

На нашем литературном портале можно бесплатно читать книгу UNIX: разработка сетевых приложений, Стивенс Уильям Ричард-- . Жанр: ОС и Сети. Онлайн библиотека дает возможность прочитать весь текст и даже без регистрации и СМС подтверждения на нашем литературном портале bazaknig.info.
UNIX: разработка сетевых приложений
Название: UNIX: разработка сетевых приложений
Дата добавления: 16 январь 2020
Количество просмотров: 381
Читать онлайн

UNIX: разработка сетевых приложений читать книгу онлайн

UNIX: разработка сетевых приложений - читать бесплатно онлайн , автор Стивенс Уильям Ричард

Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.

Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала

Перейти на страницу:
Подготовка msghdr для recvmsg

19-24
 Мы записываем значения в неизменяемые поля структур
msghdr
и
iovec
, которые будут передаваться функции
recvmsg
.

Бесконечный цикл для считывания всех ICMP-сообщений

25-37
 Основной цикл программы является бесконечным циклом, считывающим все пакеты, возвращаемые на символьный сокет ICMP. Вызывается функция
gettimeofday
для регистрации времени получения пакета, а затем вызывается соответствующая функция протокола (
proc_v4
или
proc_v6
) для обработки ICMP-сообщения.

В листинге 28.5 приведена функция

tv_sub
, вычисляющая разность двух структур
timeval
и сохраняющая результат в первой из них.

Листинг 28.5. Функция tv_sub: вычитание двух структур timeval

//lib.tv_sub.c

 1 #include "unp.h"

 2 void

 3 tv_sub(struct timeval *out, struct timeval *in)

 4 {

 5  if ((out->tv_usec -= in->tv_usec) < 0) { /* out -= in */

 6   --out->tv_sec;

 7   out->tv_usec += 1000000;

 8  }

 9  out->tv_sec -= in->tv_sec;

10 }

В листинге 28.6 приведена функция

proc_v4
, обрабатывающая все принимаемые сообщения ICMPv4. Можно также обратиться к рис. А.1, на котором изображен формат заголовка IPv4. Кроме того, следует осознавать, что к тому моменту, когда процесс получает на символьном сокете ICMP-сообщение, ядро уже проверило, что основные поля в заголовке IPv4 и в сообщении ICMPv4 действительны [128, с. 214, с. 311].

Листинг 28.6. Функция proc_v4: обработка сообщений ICMPv4

//ping/prov_v4.c

 1 #include "ping.h"

 2 void

 3 proc_v4(char *ptr, ssize_t len, struct msghdr *msg, struct timeval *tvrecv)

 4 {

 5  int hlen1, icmplen;

 6  double rtt;

 7  struct ip *ip;

 8  struct icmp *icmp;

 9  struct timeval *tvsend;

10  ip = (struct ip*)ptr; /* начало IP-заголовка */

11  hlen1 = ip->ip_hl << 2; /* длина IP-заголовка */

12  if (ip->ip_p != IPPROTO_ICMP)

13   return; /* не ICMP */

14  icmp = (struct icmp*)(ptr + hlen1); /* начало ICMP-заголовка */

15  if ((icmplen = len - hlen1) < 8)

16   return; /* плохой пакет */

17  if (icmp->icmp_type == ICMP_ECHOREPLY) {

18   if (icmp->icmp_id != pid)

19    return; /* это не ответ на наш ECHO_REQUEST */

20   if (icmplen < 16)

21    return; /* недостаточно данных */

22  tvsend = (struct timeval*)icmp->icmp_data;

23  tv_sub(tvrecv, tvsend);

24  rtt = tvrecv->tv_sec * 1000.0 + tvrecv->tv_usec / 1000.0;

25  printf("%d bytes from %s: seq=%u, ttl=%d, rtt=%.3f msn",

26   icmplen, Sock_ntop_host(pr->sarecv, pr->salen),

27   icmp->icmp_seq, ip->ip_ttl, rtt);

28  } else if (verbose) {

29   printf(" %d bytes from %s: type = %d, code = %dn",

30   icmplen, Sock_ntop_host(pr->sarecv, pr->salen),

31   icmp->icmp_type, icmp->icmp_code);

32  }

33 }

Извлечение указателя на ICMP-заголовок

10-16
 Значение поля длины заголовка IPv4, умноженное на 4, дает размер заголовка IPv4 в байтах. (Следует помнить, что IPv4-заголовок может содержать параметры.) Это позволяет нам установить указатель icmp так, чтобы он указывал на начало ICMP-заголовка. Мы проверяем, относится ли данный пакет к протоколу ICMP и имеется ли в нем достаточно данных для проверки временной отметки, включенной нами в эхо-запрос. На рис. 28.3 приведены различные заголовки, указатели и длины, используемые в коде.

UNIX: разработка сетевых приложений - img_148.png

Рис. 28.3. Заголовки, указатели и длина при обработке ответов ICMPv4

Проверка эхо-ответа ICMP

17-21
 Если сообщение является эхо-ответом ICMP, то необходимо проверить поле идентификатора, чтобы выяснить, относится ли этот ответ к посланному данным процессом запросу. Если программа ping запущена на одном узле несколько раз, каждый процесс получает копии всех полученных ICMP-сообщений.

22-27
 Путем вычитания времени отправки сообщения (содержащегося в части ICMP-ответа, отведенной под дополнительные данные) из текущего времени (на которое указывает аргумент функции
tvrecv
) вычисляется значение RTT. Время RTT преобразуется из микросекунд в миллисекунды и выводится на экран вместе с полем порядкового номера и полученным значением TTL. Поле порядкового номера позволяет пользователю проследить, не были ли пакеты пропущены, переупорядочены или дублированы, а значение TTL показывает количество транзитных узлов между двумя узлами.

Вывод всех полученных ICMP-сообщений при включении параметра verbose

28-32
 Если пользователем указан параметр командной строки
-v
, также выводятся поля типа и кода из всех других полученных ICMP-сообщений.

Обработка сообщений ICMPv6 управляется функцией

proc_v6
, приведенной в листинге 28.8. Она аналогична функции
proc_v4
, представленной в листинге 28.6. Однако поскольку символьные сокеты IPv6 не передают процессу заголовок IPv6, ограничение на количество транзитных узлов приходится получать в виде вспомогательных данных. Для этого нам приходится подготавливать сокет функцией
init_v6
, представленной в листинге 28.7.

Перейти на страницу:
Комментариев (0)
название