Уильям Стивенс - UNIX: разработка сетевых приложений
- Название:UNIX: разработка сетевых приложений
- Автор:
- Жанр:
- Издательство:Питер
- Год:2007
- Город:Санкт-Петербург
- ISBN:5-94723-991-4
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Уильям Стивенс - UNIX: разработка сетевых приложений краткое содержание
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
UNIX: разработка сетевых приложений - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
■ SIOCSARP
. Добавляет новую запись в кэш ARP или изменяет существующую запись. arp_pa
— это структура адреса сокета Интернета, содержащая IP-адрес, a arp_ha
— это общая структура адреса сокета с элементом ss_family
, равным AF_UNSPEC
, и элементом sa_data
, содержащим аппаратный адрес (например, 6-байтовый адрес Ethernet). Два флага ATF_PERM
и ATF_PUBL
могут быть заданы приложением. Два других флага, ATF_INUSE
и ATF_COM
, устанавливаются ядром.
■ SIOCDARP
. Удаляет запись из кэша ARP. Вызывающий процесс задает интернет-адрес удаляемой записи.
■ SIOCGARP
. Получает запись из кэша ARP. Вызывающий процесс задает интернет-адрес, и соответствующий адрес Ethernet возвращается вместе с флагами.
Добавлять или удалять записи может только привилегированный пользователь. Эти три вызова обычно делает программа arp
.
Запросы функции ioctl, связанные с ARP, не поддерживаются в некоторых более новых системах, использующих для описанных операций ARP маршрутизирующие сокеты.
Обратите внимание, что невозможно с помощью функции ioctl
перечислить все записи кэша ARP. Большинство версий команды arp
при использовании флага -a
(перечисление всех записей кэша ARP) считывают память ядра ( /dev/kmem
), чтобы получить текущее содержимое кэша ARP. Мы увидим более простой (и предпочтительный) способ, основанный на применении функции sysctl
, описанной в разделе 18.4.
Пример: вывод аппаратного адреса узла
Теперь мы используем нашу функцию my_addrs
для того, чтобы возвратить все IP-адреса узла. Затем для каждого IP-адреса мы делаем вызов SIOCGARP
функции ioctl
, чтобы получить и вывести аппаратные адреса. Наша программа показана в листинге 17.10.
Листинг 17.10. Вывод аппаратного адреса узла
//ioctl/prmac.c
1 #include "unpifi.h"
2 #include
3 int
4 main(int argc, char **argv)
5 {
6 int sockfd;
7 struct ifi_info *ifi;
8 unsigned char *ptr;
9 struct arpreq arpreq;
10 struct sockaddr_in *sin;
11 sockfd = Socket(AF_INET, SOCK_DGRAM, 0);
12 for (ifi = get_ifi_info(AF_INET, 0); ifi != NULL; ifi = ifi->ifi_next) {
13 printf("%s: ", Sock_ntop(ifi->ifi_addr, sizeof(struct sockaddr_in)));
14 sin = (struct sockaddr_in*)&arpreq.arp_pa;
15 memcpy(sin, ifi->ifi_addr, sizeof(struct sockaddr_in));
16 if (ioctl(sockfd, SIOCGARP, &arpreq)
17 err_ret("ioctl SIOCGARP");
18 continue;
19 }
20 ptr = &arpreq.arp_ha.sa_data[0];
21 printf("%x:%x:%x:%x:%x:%x\n", *ptr, *(ptr+1),
22 *(ptr+2), *(ptr+3), *(ptr+4), *(ptr+5));
23 }
24 exit(0);
25 }
12
Мы вызываем функцию get_ifi_info
, чтобы получить IP-адреса узла, а затем выполняем цикл по всем адресам.
13
Мы выводим IP-адреса, используя функцию inet_ntop
. Мы просим функцию get_ifi_info
возвращать только адреса IPv4, так как ARP с IPv6 не используется.
14-19
Мы заполняем структуру arp_pa
как структуру адреса сокета IPv4, содержащую адрес IPv4. Вызывается функция ioctl
, и если она возвращает ошибку (например, указанный адрес относится к интерфейсу, не поддерживающему ARP), мы выводим сообщение и переходим к следующему адресу.
20-22
Выводится аппаратный адрес, возвращаемый ioctl
.
При запуске этой программы на нашем узле hpux
мы получаем:
hpux % prmac
192.6.38.100: 0:60:b0:c2:68:9b
192.168.1.1: 0:60:b0:b2:28:2b
127.0.0.1: ioctl SIOCGARP: Invalid argument
17.9. Операции с таблицей маршрутизации
Для работы с таблицей маршрутизации предназначены два вызова функции ioctl
. Эти два вызова требуют, чтобы третий аргумент функции ioctl был указателем на структуру rtentry
, которая определяется в заголовочном файле . Обычно эти вызовы исходят от программы route
. Их может делать только привилегированный пользователь. При наличии маршрутизирующих сокетов (глава 18) для выполнения этих запросов используются именно они, а не функция ioctl
.
■ SIOCADDRT
. Добавить запись в таблицу маршрутизации.
■ SIOCDELRT
. Удалить запись из таблицы маршрутизации.
Нет способа с помощью функции ioctl
перечислить все записи таблицы маршрутизации. Эту операцию обычно выполняет программа netstat
с флагом -r
. Программа получает таблицу маршрутизации, считывая память ядра ( /dev/kmem
). Как и в случае с просмотром кэша ARP, в разделе 18.4 мы увидим более простой (и предпочтительный) способ, предоставляемый функцией sysctl
.
17.10. Резюме
Команды функции ioctl
, используемые в сетевых приложениях, можно разделить на шесть категорий:
1. Операции с сокетами (находимся ли мы на отметке внеполосных данных?).
2. Операции с файлами (установить или сбросить флаг отсутствия блокировки).
3. Операции с интерфейсами (возвратить список интерфейсов, получить широковещательный адрес).
4. Операции с кэшем ARP (создать, изменить, получить, удалить).
5. Операции с таблицей маршрутизации (добавить или удалить).
6. Операции с потоками STREAMS (см. главу 31).
Мы будем использовать операции с сокетами и файлами, а получение списка интерфейсов — это настолько типичная операция, что для этой цели мы разработали собственную функцию. Мы будем применять ее много раз в оставшейся части книги. Вызовы функции ioctl
с кэшем ARP и таблицей маршрутизации используются лишь несколькими специализированными программами.
Упражнения
1. В разделе 17.7 мы сказали, что широковещательный адрес, возвращаемый запросом SIOCGIFBRDADDR, возвращается в элементе ifr_broadaddr
. Но на с. 173 [128] сказано, что он возвращается в элементе ifr_dstaddr
. Имеет ли это значение?
2. Измените программу get_ifi_info
так, чтобы она делала первый вызов SIOCGIFCONF
для одной структуры ifreq
, а затем каждый раз в цикле увеличивайте длину на размер одной из этих структур. Затем поместите в цикл операторы, которые выводили бы размер буфера при каждом вызове независимо от того, возвращает функция ioctl
ошибку или нет, и при успешном выполнении выведите возвращаемую длину буфера. Запустите программу prifinfo
и посмотрите, как ваша система обрабатывает вызов, когда размер буфера слишком мал. Выведите также семейство адресов для всех возвращаемых структур, семейство адресов которых не совпадает с указанным в первом аргументе функции get_ifi_info
, чтобы увидеть, какие еще структуры возвращает ваша система.
3. Измените функцию get_ifi_info
так, чтобы она возвращала информацию об адресе с альтернативным именем, если дополнительный адрес находится не в той подсети, в которой находится предыдущий адрес для данного интерфейса. Таким образом, наша версия из раздела 17.6 будет игнорировать альтернативные имена в диапазоне от 206.62.226.44 до 206.62.226.46, и это вполне нормально, поскольку они находятся в той же подсети, что и первичный адрес интерфейса 206.62.226.33. Но если альтернативное имя находится в другой подсети, допустим 192.3.4.5, возвратите структуру ifi_info
с информацией о дополнительном адресе.
Интервал:
Закладка: