-->

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

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

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

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

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

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

Перейти на страницу:

Листинг 28.7. Функция init_v6: подготовка сокета

 1 void

 2 init_v6()

 3 {

 4 #ifdef IPV6

 5  int on = 1;

 6  if (verbose == 0) {

 7   /* установка фильтра, пропускающего только пакеты ICMP6_ECHO_REPLY. если

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

 8   struct icmp6_filter myfilt;

 9   ICMP6_FILTER_SETBLOCKALL(&myfilt);

10   ICMP6_FILTER_SETPASS(ICMP6_ECHO_REPLY, &myfilt);

11   setsockopt(sockfd, IPPROTO_IPV6, ICMP6_FILTER, &myfilt,

12    sizeof(myfilt));

13   /* игнорируем ошибку, потому что фильтр - необязательная оптимизация */

14  }

15  /* следующую ошибку тоже игнорируем; придется обойтись без вывода

       ограничения на количество транзитных узлов */

16 #ifdef IPV6_RECVHOPLIMIT

17  /* RFC 3542 */

18  setsockopt(sockfd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on, sizeof(on));

19 #else

20  /* RFC 2292 */

21  setsockopt(sockfd, IPPROTO_IPV6, IPV6_HOPLIMIT, &on, sizeof(on));

22 #endif

23 #endif

24 }

Приведенная в листинге 28.8 функция

proc_v6
обрабатывает входящие пакеты.

Листинг 28.8. Функция proc_v6: обработка сообщений ICMPv6

//ping/proc_v6.c

 1 #include "ping.h"

 2 void

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

 4 {

 5 #ifdef IPV6

 6  double rtt;

 7  struct icmp6_hdr *icmp6;

 8  struct timeval *tvsend;

 9  struct cmsghdr *cmsg;

10  int hlim;

11  icmp6 = (struct icmp6_hdr*)ptr;

12  if (len < 8)

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

14  if (icmp6->icmp6_type == ICMP6_ECHO_REPLY) {

15   if (icmp6->icmp6_id != pid)

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

17   if (len < 16)

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

19   tvsend = (struct timeval*)(icmp6 + 1);

20   tv_sub(tvrecv, tvsend);

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

22   hlim = -1;

23   for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL;

24    cmsg = CMSG_NXTHDR(msg, cmsg)) {

25    if (cmsg->cmsg_level == IPPROTO_IPV6 &&

26     cmsg->cmsg_type == IPV6_HOPLIMIT) {

27     hlim = *(u_int32_t*)CMSG_DATA(cmsg);

28     break;

29    }

30   }

31   printf("%d bytes from %s; seq=%u, hlim=",

32    len, Sock_ntop__host(pr->sarecv, pr->salen), icmp6->icmp6_seq);

33   if (hlim == -1)

34    printf("???"); /* отсутствуют вспомогательные данные */

35   else

36    printf("%d", hlim);

37   printf(", rtt=%.3f msn", rtt);

38  } else if (verbose) {

39   printf(" %d bytes from type = %d, code = %dn",

40    len, Sock_ntop_host(pr->sarecv, pr->salen);

41   icmp6->icmp6, type, icmp6->icmp6_code);

42  }

43 #endif /* IPV6 */

44 }

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

11-13
 Заголовок ICMPv6 возвращается внутри данных при чтении из сокета. (Напомним, что дополнительные заголовки IPv6, если они присутствуют, всегда возвращаются не как стандартные данные, а как вспомогательные.) На рис. 28.4 приведены различные заголовки, указатели и длина, используемые в коде.

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

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

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

14-37
 Если ICMP-сообщение является эхо-ответом, то чтобы убедиться, что ответ предназначен для нас, мы проверяем поле идентификатора. Если это подтверждается, то вычисляется значение RTT, которое затем выводится вместе с порядковым номером и предельным количеством транзитных узлов IPv4. Ограничение на количество транзитных узлов мы получаем из вспомогательных данных
IPV6_HOPLIMIT
.

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

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

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

sig_alrm
, приведенная в листинге 28.9. В листинге 28.4 функция readloop вызывает обработчик сигнала один раз для отправки первого пакета. Эта функция в зависимости от протокола вызывает функцию
send_v4
или
send_v6
для отправки эхо-запроса ICMP и далее программирует запуск другого сигнала
SIGALRM
через 1 с.

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