-->

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

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

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

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

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

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

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

Листинг 28.9. Функция sig_alrm: обработчик сигнала SIGALRM

//ping/sig_alrm.c

 1 #include "ping.h"

 2 void

 3 sig_alrm(int signo)

 4 {

 5  (*pr->fsend)();

 6  alarm(1);

 7  return;

 8 }

Функция

send_v4
, приведенная в листинге 28.10, строит ICMPv4 сообщение эхо-запроса и записывает его в символьный сокет.

Листинг 28.10. Функция send_v4: построение эхо-запроса ICMPv4 и его отправка

//ping/send_v4.c

 1 #include "ping.h"

 2 void

 3 send_v4(void)

 4 {

 5  int len;

 6  struct icmp *icmp;

 7  icmp = (struct icmp*)sendbuf;

 8  icmp->icmp_type = ICMP_ECHO;

 9  icmp->icmp_code = 0;

10  icmp->icmp_id = pid;

11  icmp->icmp_seq = nsent++;

12  memset(icmp->icmp_data, 0xa5, datalen); /* заполнение по шаблону */

13  Gettimeofday((struct timeval*)icmp->icmp_data, NULL);

14  len = 8 + datalen; /* контрольная сумма по заголовку и данным */

15  icmp->icmp_cksum = 0;

16  icmp->icmp_cksum = in_cksum((u_short*)icmp, len);

17  Sendto(sockfd, sendbuf, len, 0, pr->sasend, pr->salen);

18 }

Формирование ICMP-сообщения

7-13
 ICMPv4 сообщение сформировано. В поле идентификатора установлен идентификатор нашего процесса, а порядковый номер установлен как глобальная переменная
nset
, которая затем увеличивается на 1 для следующего пакета. Текущее время сохраняется в части данных ICMP-сообщения.

Вычисление контрольной суммы ICMP

14-16
 Для вычисления контрольной суммы ICMP значение поля контрольной суммы устанавливается равным 0, затем вызывается функция
in_cksum
, а результат сохраняется в поле контрольной суммы. Контрольная сумма ICMPv4 вычисляется по ICMPv4-заголовку и всем следующим за ним данным.

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

17
 ICMP-сообщение отправлено на символьный сокет. Поскольку параметр сокета
IP_HDRINCL
не установлен, ядро составляет заголовок IPv4 и добавляет его в начало нашего буфера.

Контрольная сумма Интернета является суммой обратных кодов 16-разрядных значений. Если длина данных является нечетным числом, то для вычисления контрольной суммы к данным дописывается один нулевой байт. Перед вычислением контрольной суммы поле контрольной суммы должно быть установлено в 0. Такой алгоритм применяется для вычисления контрольных сумм IPv4, ICMPv4, IGMPv4, ICMPv6, UDP и TCP. В RFC 1071 [12] содержится дополнительная информация и несколько числовых примеров. В разделе 8.7 книги [128] более подробно рассказывается об этом алгоритме, а также приводится более эффективная его реализация. В нашем случае контрольную сумму вычисляет функция

in_cksum
, приведенная в листинге 28.11.

Листинг 28.11. Функция in_cksum: вычисление контрольной суммы Интернета

//libfree/in_cksum.c

 1 uint16_t

 2 in_cksum(uint16_t *addr, int len)

 3 {

 4  int nleft = len;

 5  uint32_t sum = 0;

 6  uint16_t *w = addr;

 7  uint16_t answer = 0;

 8  /*

 9   * Наш алгоритм прост: к 32-разрядному аккумулятору sum мы добавляем

10   * 16-разрядные слова, а затем записываем все биты переноса из старших

11   * 16 разрядов в младшие 16 разрядов.

12   */

13  while (nleft > 1) {

14   sum += *w++;

15   nleft -= 2;

16  }

17  /* при необходимости добавляем четный байт */

18  if (nleft == 1) {

19   *(unsigned char*)(&answer) = *(unsigned char*)w;

20   sum += answer;

21  }

22  /* перемещение битов переноса из старших 16 разрядов в младшие */

23  sum = (sum >> 16) + (sum & 0xffff); /* добавление старших 16 к младшим */

24  sum += (sum >> 16); /* добавление переноса */

25  answer = ~sum; /* обрезаем по 16 разрядам */

26  return(answer);

27 }

Алгоритм вычисления контрольной суммы Интернета

1-27
 Первый цикл
while
вычисляет сумму всех 16-битовых значений. Если длина нечетная, то к сумме добавляется конечный байт. Алгоритм, приведенный в листинге 28.11, является простым алгоритмом, подходящим для программы
ping
, но неудовлетворительным для больших объемов вычислений контрольных сумм, производимых ядром.

ПРИМЕЧАНИЕ

Эта функция взята из общедоступной версии программы ping, написанной Майком Мюссом (Mike Muuss).

Последней функцией нашей программы

ping
является функция
send_v6
, приведенная в листинге 28.12, которая формирует и посылает эхо-запросы ICMPv6.

Функция

send_v6
аналогична функции
send_v4
, но обратите внимание, что она не вычисляет контрольную сумму. Как отмечалось ранее, поскольку для вычисления контрольной суммы ICMPv6 используется адрес отправителя из IPv6-заголовка, данная контрольная сумма вычисляется для нас ядром, после того как ядро выяснит адрес отправителя.

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