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

Тут можно читать онлайн Уильям Стивенс - UNIX: разработка сетевых приложений - бесплатно ознакомительный отрывок. Жанр: comp-osnet, издательство Питер, год 2007. Здесь Вы можете читать ознакомительный отрывок из книги онлайн без регистрации и SMS на сайте лучшей интернет библиотеки ЛибКинг или прочесть краткое содержание (суть), предисловие и аннотацию. Так же сможете купить и скачать торрент в электронном формате fb2, найти и слушать аудиокнигу на русском языке или узнать сколько частей в серии и всего страниц в публикации. Читателям доступно смотреть обложку, картинки, описание и отзывы (комментарии) о произведении.
  • Название:
    UNIX: разработка сетевых приложений
  • Автор:
  • Жанр:
  • Издательство:
    Питер
  • Год:
    2007
  • Город:
    Санкт-Петербург
  • ISBN:
    5-94723-991-4
  • Рейтинг:
    4.33/5. Голосов: 91
  • Избранное:
    Добавить в избранное
  • Отзывы:
  • Ваша оценка:
    • 80
    • 1
    • 2
    • 3
    • 4
    • 5

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

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

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

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

UNIX: разработка сетевых приложений - читать книгу онлайн бесплатно (ознакомительный отрывок), автор Уильям Стивенс
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

Причина, по которой в этом примере мы используем функции sigsetjmpи siglongjmp, вместо того чтобы просто перехватывать ошибку EINTR(как мы поступили в листинге 14.1), заключается в том, что библиотечные функции захвата пакетов (которые вызываются из нашей функции udp_read) заново запускают операцию чтения в случае возвращения ошибки EINTR. Поскольку мы не хотим модифицировать библиотечные функции, единственным решением для нас является перехватывание сигнала SIGALRMи выполнение нелокального перехода (оператора goto), который возвращает управление в наш код, а не в библиотечную функцию.

Отправка запроса DNS и считывание ответа

25-26 Функция send_dns_query(см. листинг 29.8) отправляет запрос DNS на сервер имен. Функция dns_readсчитывает ответ. Мы вызываем функцию alarmдля предотвращения «вечной» блокировки функции read. Если истекает заданное (в секундах) время ожидания, генерируется сигнал SIGALRM, и наш обработчик сигнала вызывает функцию siglongjmp.

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

27-32 Если значение полученной контрольной суммы UDP равно нулю, это значит, что сервер не вычислил и не отправил контрольную сумму.

В листинге 29.7 показана наша функция sig_alrm— обработчик сигнала SIGALRM.

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

//udpcksum/udpcksum.c

1 #include "udpcksum.h"

2 #include

3 static sigjmp_buf jmpbuf;

4 static int canjump;

5 void

6 sig_alrm(int signo)

7 {

8 if (canjump == 0)

9 return;

10 siglongjmp(jmpbuf, 1);

11 }

8-10 Флаг canjumpбыл установлен в листинге 29.6 после инициализации буфера перехода функцией sigsetjmp. Если флаг был установлен, в результате вызова функции siglongjmpуправление осуществляется таким образом, как если бы функция sigsetjmpиз листинга 29.6 возвратила бы значение 1.

В листинге 29.8 показана функция send_dns_query, посылающая запрос UDP на сервер DNS. Эта функция формирует запрос DNS.

Листинг 29.8. Функция send_dns_query: отправка запроса UDP на сервер DNS

//udpcksum/senddnsquery-raw.c

6 void

7 send_dns_query(void)

8 {

9 size_t nbytes;

10 char *buf, *ptr;

11 buf = Malloc(sizeof(struct udpiphdr) + 100);

12 ptr = buf + sizeof(struct udpiphdr); /* место для заголовков IP и UDP */

13 *((uint16_t*)ptr) = htons(1234); /* идентификатор */

14 ptr += 2;

15 *((uint16_t*)ptr) = htons(0x0100); /* флаги */

16 ptr += 2;

17 *((uint16_t*)ptr) = htons(1); /* количество запросов */

18 ptr += 2;

19 *((uint16_t*)ptr) = 0; /* количество записей в ответе */

20 ptr += 2;

21 *((uint16_t*)ptr) = 0; /* количество авторитетных записей */

22 ptr += 2;

23 *((uint16_t*)ptr) = 0; /* количество дополнительных записей */

24 ptr += 2;

25 memcpy(ptr, "\001a\014root-servers\003net\000", 20);

26 ptr += 20;

27 *((uint16_t*)ptr) = htons(1); /* тип запроса = А */

28 ptr += 2;

29 *((uint16_t*)ptr) = htons(1); /* класс запроса = 1 (IP-адрес) */

30 ptr += 2;

31 nbytes = (ptr - buf) - sizeof(struct udpiphdr);

32 udp_write(buf, mbytes),

33 if (verbose)

35 printf("sent: %d bytes of data\n", nbytes);

36 }

Инициализация указателя на буфер

11-12 В буфере bufимеется место для 20-байтового заголовка IP, 8-байтового заголовка UDP и еще 100 байт для пользовательских данных. Указатель ptrустановлен на первый байт пользовательских данных.

Формирование запроса DNS

13-24 Для понимания деталей устройства дейтаграммы UDP требуется понимание формата сообщения DNS. Эту информацию можно найти в разделе 14.3 [111]. Мы присваиваем полю идентификации значение 1234, сбрасываем флаги, задаем количество запросов — 1, а затем обнуляем количество записей ресурсов (RR, resource records), получаемых в ответ, количество RR, определяющих полномочия, и количество дополнительных RR.

25-30 Затем мы формируем простой запрос, который располагается после заголовка: запрос типа А IP-адреса узла a.root-servers.net. Это доменное имя занимает 20 байт и состоит из 4 фрагментов: однобайтовая часть a, 12-байтовая часть root-servers, 3-байтовая часть netи корневая часть, длина которой занимает 0 байт. Тип запроса 1 (так называемый запрос типа А), и класс запроса также 1.

Запись дейтаграммы UDP

31-32 Это сообщение состоит из 36 байт пользовательских данных (восемь 2-байтовых полей и 20-байтовое доменное имя). Мы вызываем нашу функцию udp_writeдля формирования заголовков UDP и IP и последующей записи дейтаграммы UDP в наш символьный сокет.

В листинге 29.9 показана функция open_output, работающая с символьными сокетами.

Листинг 29.9. Функция open_output: подготовка символьного сокета

2 int rawfd; /* символьный сокет */

3 void

4 open_output(void)

5 {

6 int on=1;

7 /*

8 * Для отправки IP-дейтаграмм нужен символьный сокет

9 * Для его создания нужны права привилегированного пользователя.

10 * Кроме того, необходимо указать параметр сокета IP_HDRINCL.

11 */

12 rawfd = Socket(dest->sa_family, SOCK_RAW, 0);

13 Setsockopt(rawfd, IPPROTO_IP, IP_HDRINCL, &on., sizeof(on));

14 }

Объявление дескриптора символьного сокета

2 Мы объявляем глобальную переменную, в которой будет храниться дескриптор символьного сокета.

Создание сокета и установка IP_HDRINCL

7-13 Мы создаем символьный сокет и включаем параметр сокета IP_HDRINCL. Это позволяет нам формировать IP-дейтаграммы целиком, включая заголовок IP.

В листинге 29.10 показана наша функция udp_write, которая формирует заголовки IP и UDP, а затем записывает дейтаграмму в символьный сокет.

Листинг 29.10. Функция udp_write: формирование заголовков UDP и IP и запись дейтаграммы IP в символьный сокет

//udpcksum/udpwrite.c

19 void

20 udp_write(char *buf, int userlen)

21 {

22 struct udpiphdr *ui;

23 struct ip *ip;

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

25 ip = (struct ip*)buf;

26 ui = (struct udpiphdr*)buf;

27 bzero(ui, sizeof(*ui));

28 /* добавляем 8 к длине псевдозаголовка */

29 ui->ui_len = htons((uint16_t)(sizeof(struct udphdr) + userlen));

30 /* добавление 28 к длине IP-дейтаграммы */

31 userlen += sizeof(struct udpiphdr);

32 ui->ui_pr = IPPROTO_UDP;

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

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-заголовка */

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать


Уильям Стивенс читать все книги автора по порядку

Уильям Стивенс - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки LibKing.




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


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


Понравилась книга? Поделитесь впечатлениями - оставьте Ваш отзыв или расскажите друзьям

Напишите свой комментарий
x