Уильям Стивенс - UNIX: разработка сетевых приложений
- Название:UNIX: разработка сетевых приложений
- Автор:
- Жанр:
- Издательство:Питер
- Год:2007
- Город:Санкт-Петербург
- ISBN:5-94723-991-4
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Уильям Стивенс - UNIX: разработка сетевых приложений краткое содержание
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
UNIX: разработка сетевых приложений - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
Библиотека скрывает большую часть деталей формирования заголовков IP, UDP и TCP и обеспечивает приложению простой и переносимый интерфейс для отправки пакетов канального уровня и IP-пакетов через символьные сокеты. Как и libcap
, библиотека libnet
содержит достаточно много функций. Мы приведем пример использования небольшой их части, предназначенной для работы с символьными сокетами, но в следующем разделе. Для сравнения там же будет приведен код, непосредственно работающий с символьными сокетами. Все функции библиотеки начинаются с префикса libnet_
. За более подробным их описанием вы можете обратиться к странице руководства libnet
или к доступной в Сети документации.
Библиотека libnet свободно доступна по адресу http://www.packetfactory.net/libnet/. Руководство находится по адресу http://www.packetfactory.net/libnet/manual. На момент написания этой книги в Сети имелось руководство только по устаревшей версии 1.0. Актуальная версия 1.1 имеет значительно отличающийся интерфейс. В нашем примере используется API версии 1.1.
29.7. Анализ поля контрольной суммы UDP
Теперь мы приступаем к рассмотрению примера, в котором отсылается дейтаграмма UDP, содержащая запрос UDP к серверу имен, а затем считывается ответ с помощью библиотеки захвата пакетов. Цель данного примера — установить, вычисляется на сервере имен контрольная сумма UDP или нет. В случае IPv4 вычисление контрольной суммы не является обязательным. В большинстве систем в настоящее время вычисление контрольных сумм по умолчанию включено, но, к сожалению, в более старых системах, в частности SunOS 4.1.x, оно по умолчанию отключено. В настоящее время все системы, а особенно система, в которой работает сервер имен, всегда должны работать с включенными контрольными суммами UDP, поскольку поврежденные (содержащие ошибки) дейтаграммы могут повредить базу данных сервера.
Включение и выключение контрольных сумм обычно осуществляется сразу для всей системы, как показано в приложении Е [111].
Мы формируем дейтаграмму UDP (запрос DNS) и записываем ее в символьный сокет. Параллельно мы проделаем то же самое с помощью libnet
. Для отправки запроса мы могли бы использовать обычный сокет UDP, но мы хотим показать, как использовать параметр сокета IP_HDRINCL
для создания полной дейтаграммы IP.
Нет возможности получить контрольную сумму UDP при чтении из обычного сокета UDP, а также считывать пакеты UDP или TCP, используя символьный сокет (см. раздел 28.4). Следовательно, путем захвата пакетов нам нужно получить целую дейтаграмму UDP, содержащую ответ сервера имен.
Затем мы исследуем поле контрольной суммы UDP в заголовке UDP, и если оно равно нулю, это означает, что на сервере отключено вычисление контрольной суммы.
Действие нашей программы иллюстрирует рис. 29.3. Мы записываем наши собственные дейтаграммы UDP в символьный сокет и считываем ответы, используя библиотеку libcap
. Обратите внимание, что UDP также получает ответ сервера имен и отвечает сообщением о недоступности порта ICMP, так как ничего не знает о номере порта, выбранном нашим приложением. Сервер имен игнорирует эту ошибку ICMP. Также можно отметить, что написать подобную тестовую программу, использующую TCP, было бы сложнее, даже несмотря на то, что мы с легкостью можем записывать свои собственные сегменты TCP. Дело в том, что любой ответ на сегмент TCP, который мы генерируем, обычно инициирует отправку протоколом TCP ответного сегмента RST туда, куда был послан первый сегмент.

Рис. 29.4. Функции, которые используются в программе udpcksum
В листинге 29.1 [1] Все исходные коды программ, опубликованные в этой книге, вы можете найти по адресу http://www.piter.com.
показан заголовочный файл udpcksum.h
, в который включен наш базовый заголовочный файл unp.h
, а также различные системные заголовки, необходимые для получения доступа к определениям структур для заголовков пакетов IP и UDP.
Листинг 29.1. Заголовочный файл udpcksum.h
//udpcksum/udpcksum.h
1 #include "unp.h"
2 #include
3 #include /* необходим для ip.h */
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #define TTL_OUT 64 /* исходящее TTL */
12 /* объявление глобальных переменных */
13 extern struct sockaddr *dest, *local;
14 extern socklen_t destlen, locallen;
15 extern int datalink;
16 extern char *device;
17 extern pcap_t *pd;
18 extern int rawfd;
19 extern int snaplen;
20 extern int verbose;
21 extern int zerosum;
22 /* прототипы функций */
23 void cleanup(int);
24 char *next_pcap(int*);
25 void open_output(void);
26 void open_pcap(void);
27 void send_dns_query(void);
28 void test_udp(void);
29 void udp_write(char*, int);
30 struct udpiphdr *udp_read(void);
3-10
Для работы с полями заголовков IP и UDP требуются дополнительные заголовочные файлы Интернета.
11-30
Мы определяем некоторые глобальные переменные и прототипы для своих собственных функций, которые вскоре покажем.
Первая часть функции main
показана в листинге 29.2.
Листинг 29.2. Функция main: определения
//udpcksum/main.c
1 #include "udpcksum.h"
2 /* определение глобальных переменных */
3 struct sockaddr *dest, *local;
4 struct sockaddr_in locallookup;
5 socklen_t destlen, locallen;
6 int datalink; /* из pcap_datalink(), файл */
7 char *device; /* устройство pcap */
8 pcap_t *pd; /* указатель на структуру захваченных пакетов */
9 int rawfd; /* символьный сокет */
10 int snaplen = 200; /* объем захваченных данных */
11 int verbose;
12 int zerosum; /* отправка UDP-запроса без контрольной суммы */
13 static void usage(const char*);
14 int
15 main(int argc, char *argv[])
16 {
17 int c, lopt=0;
18 char *ptr, localname[1024], *localport;
19 struct addrinfo *aip;
В следующей части функции main
, представленной в листинге 29.3, обрабатываются аргументы командной строки.
Листинг 29.3. Функция main: обработка аргументов командной строки
//udpcksum/main.c
20 opterr = 0; /* отключаем запись сообщений getopt() в stderr */
21 while ((с = getopt(argc, argv, "0i:l:v")) != -1) {
22 switch (с) {
23 case '0':
24 zerosum = 1;
25 break;
26 case 'i';
27 device = optarg; /* устройство pcap */
28 break;
29 case 'l'; /* локальный IP адрес и номер порта; a.b.c.d.p */
30 if ((ptr = strrchr(optarg, '.')) == NULL)
31 usage("invalid -l option");
32 *ptr++ = 0; /* нуль заменяет последнюю точку. */
33 local port = ptr; /* имя сервиса или номер порта */
34 strncpy(localname, optarg, sizeof(localname));
35 lopt = 1;
36 break;
37 case 'v':
Интервал:
Закладка: