-->

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

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

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

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

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

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

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

33  ui->ui_src.s_addr = ((struct sockaddr_in*)local)->sin_addr.s_addr;

34  ui->ui_dst.s_addr = ((struct sockaddr_in*)dest)->sin_addr.s_addr;

35  ui->ui_sport = ((struct sockaddr_in*)local)->sin_port;

36  ui->ui_dport = ((struct sockaddr_in*)dest)->sin_port;

37  ui->ui_ulen = ui->ui_len;

38  if (zerosum == 0) {

39 #if 1 /* заменить на if 0 для Solaris 2.x. x < 6 */

40   if ((ui->ui_sum = m_cksum((u_int16_t*)in, userlen)) == 0)

41   ui->ui_sum = 0xffff;

42 #else

43   ui->ui_sum = ui->ui_len;

44 #endif

45  }

46  /* заполнение оставшейся части IP-заголовка */

47  /* функция p_output() вычисляет и сохраняет контрольную сумму IP */

48  ip->ip_v = IPVERSION;

49  ip->ip_hl = sizeof(struct ip) >> 2;

50  ip->ip_tos = 0;

51 #if defined(linux) || defined(__OpenBSD__)

52  ip->ip_len = htons(userlen); /* сетевой порядок байтов */

53 #else

54  ip->ip_len = userlen; /* порядок байтов узла */

55 #endif

56  ip->ip_id = 0; /* это пусть устанавливает уровень IP */

57  ip->ip_off = 0; /* смещение флагов, флаги MF и DF */

58  ip->ip_ttl = TTL_OUT;

59  Sendto(rawfd, buf, userlen, 0, dest, destlen);

60 }

Инициализация указателей на заголовки пакетов

24-26
 Указатель
ip
указывает на начало заголовка IP (структуру
ip
), а указатель
ui
указывает на то же место, но структура
udpiphdr
является объединением заголовков IP и UDP.

Обнуление заголовка

27
 Мы явным образом записываем в заголовок нули, чтобы предотвратить учет случайного мусора, который мог остаться в буфере, при вычислении контрольной суммы.

Обновление значений длины

28-31
 Переменная
ui_len
— это длина дейтаграммы UDP: количество байтов пользовательских данных плюс размер заголовка UDP (8 байт). Переменная
userlen
(количество байтов пользовательских данных, которые следуют за заголовком UDP) увеличивается на 28 (20 байт на заголовок IP и 8 байт на заголовок UDP), для того чтобы соответствовать настоящему размеру дейтаграммы IP.

Заполнение заголовка UDP и вычисление контрольной суммы UDP

32-45
При вычислении контрольной суммы UDP учитывается не только заголовок и данные UDP, но и поля заголовка IP. Эти дополнительные поля заголовка IP образуют то, что называется псевдозаголовком (pseudoheader). Включение псевдозаголовка обеспечивает дополнительную проверку на то, что если значение контрольной суммы верно, то дейтаграмма была доставлена на правильный узел и с правильным кодом протокола. В указанных строках располагаются операторы инициализации полей в IP-заголовке, формирующих псевдозаголовок. Данный фрагмент кода несколько запутан, но его объяснение приводится в разделе 23.6 [128]. Конечным результатом является запись контрольной суммы UDP в поле
ui_sum
, если не установлен флаг
zerosum
(что соответствует наличию аргумента командной строки -0).

Если при вычислении контрольной суммы получается 0, вместо него записывается значение

0xffff
. В обратном коде эти числа совпадают, но протокол UDP устанавливает контрольную сумму в нуль, чтобы обозначить, что она вовсе не была вычислена. Обратите внимание, что в листинге 28.10 мы не проверяем, равно ли значение контрольной суммы нулю: дело в том, что в случае ICMPv4 нулевое значение контрольной суммы не означает ее отсутствия.

ПРИМЕЧАНИЕ

Следует отметить, что в Solaris 2.x, где x<6, в случаях, когда дейтаграммы UDP или сегменты TCP отправляются с символьного сокета при установленном параметре IP_HDRINCL, возникает ошибка. Контрольную сумму вычисляет ядро, а мы должны установить поле ui_sum равным длине дейтаграммы UDP.

Заполнение заголовка IP

36-49
 Поскольку мы установили параметр сокета
IP_HDRINCL
, нам следует заполнить большую часть полей в заголовке IP. (В разделе 28.3 обсуждается запись в символьный сокет при включенном параметре
IP_HDRINCL
.) Мы присваиваем полю идентификации нуль (
ip_id
), что указывает IP на необходимость задания значения этого поля. IP также вычисляет контрольную сумму IP, а функция
sendto
записывает дейтаграмму IP.

ПРИМЕЧАНИЕ

Обратите внимание, что поле ip_len может иметь либо сетевой порядок байтов, либо порядок байтов узла. Это типичная проблема с совместимостью, возникающая при использовании символьных сокетов.

Следующая функция — это

udp_read
, показанная в листинге 29.11. Она вызывается из кода, представленного в листинге 29.6.

Листинг 29.11. Функция udp_read: чтение очередного пакета из устройства захвата пакетов

//udpcksum/udpread.c

 7 struct udpiphdr*

 8 udp_read(void)

 9 {

10  int len;

11  char *ptr;

12  struct ether_header *eptr;

13  for (;;) {

14   ptr = next_pcap(&amp;len);

15   switch (datalink) {

16   case DLT_NULL: /* заголовок обратной петли = 4 байта */

17    return (udp_check(ptr + 4, len — 4));

18   case DLT_EN10MB:

19    eptr = (struct ether_header*)ptr;

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