Уильям Стивенс - UNIX: разработка сетевых приложений
- Название:UNIX: разработка сетевых приложений
- Автор:
- Жанр:
- Издательство:Питер
- Год:2007
- Город:Санкт-Петербург
- ISBN:5-94723-991-4
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Уильям Стивенс - UNIX: разработка сетевых приложений краткое содержание
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
UNIX: разработка сетевых приложений - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
Листинг 18.2.Пять структур, возвращаемых с маршрутизирующими сообщениями
struct rt_msghdr { /* из */
u_short rtm_msglen; /* для пропуска некорректных сообщений */
u_char rtm_version; /* для обеспечения двоичной совместимости в будущем */
u_char rtm_type; /* тип сообщения */
u_short rtm_index; /* индекс интерфейса, с которым связан адрес */
int rtm_flags; /* флаги */
int rtm_addrs; /* битовая маска, идентифицирующая sockaddr (структуру адреса
сокета) в msg */
pid_t rtm_pid; /* идентификация отправителя */
int rtm_seq; /* для идентификации действия отправителем */
int rtm_errno; /* причина неудачного выполнения */
int rtm_use; /* из rtentry */
u_long rtm_inits; /* какую метрику мы инициализируем */
struct rt_metrics rtm_rmx; /* сами метрики */
};
struct if_msghdr { /* из */
u_short ifm_msglen; /* для пропуска некорректных сообщений */
u_char ifm_version; /* для обеспечения двоичной совместимости в будущем */
u_char ifm_type; /* тип сообщения */
int ifm_addrs; /* как rtm_addrs */
int ifm_flags; /* значение if_flags */
u_short ifm_index; /* индекс интерфейса, с которым связан адрес */
struct if_data ifm_data; /* статистические и другие сведения */
};
struct ifa_msghdr { /* из */
u_short ifam_msglen; /* для пропуска некорректных сообщений */
u_char ifam_version; /* для обеспечения двоичной совместимости в будущем */
u_char ifam_type; /* тип сообщения */
int ifam_addrs; /* как rtm_addrs */
int ifam_flags; /* значение ifa_flags */
u_short ifam_index; /* индекс интерфейса, с которым связан адрес */
int ifam_metric; /* значение ifa_metric */
};
struct ifma_msghdr { /* из */
u_short ifmam_msglen; /* для пропуска некорректных сообщений */
u_char ifmam_version; /* для обеспечения двоичной совместимости в будущем */
u_char ifmam_type; /* тип сообщения */
int ifmam_addrs; /* аналог rtm_addrs */
int ifmam_flags; /* значение ifa_flags */
u_short ifmam_index; /* индекс связанного ifp */
};
struct if_announcemsghdr { /* из */
u_short ifan_msglen; /* для пропуска некорректных сообщений */
u_char ifan_version; /* для обеспечения двоичной совместимости в будущем */
u_char ifan_type; /* тип сообщения */
u_short ifan_index; /* индекс связанного ifp */
char ifan_name[IFNAMSIZ]; /* название интерфейса, напр. "en0" */
u_short ifan_what; /* тип объявления */
};
Первые три элемента каждой структуры одни и те же: длина, версия и тип сообщения. Тип — это одна из констант из первого столбца табл. 18.1. Элемент длины xxx_msglen
позволяет приложению пропускать типы сообщений, которые оно не распознает.
Элементы rtm_addrs
, ifm_addrs
и ifam_addrs
являются битовыми масками, указывающими, какая из возможных восьми структур адреса сокета следует за сообщением. В табл. 18.2 показаны константы и значения для битовой маски, определяемые в заголовочном файле .
Таблица 18.2. Константы, используемые для ссылки на структуры адреса сокета в маршрутизирующих сообщениях
Битовая маска, константа | Битовая маска, значение | Индекс массива, константа | Индекс массива, значение | Структура адреса сокета содержит |
---|---|---|---|---|
RTA_DST | 0x01 | RTAX_DST | 0 | Адрес получателя |
RTA_GATEWAY | 0x02 | RTAX_GATEWAY | 1 | Адрес шлюза |
RTA_NETMASK | 0x04 | RTAX_NETMASK | 2 | Маска сети |
RTA_GENMASK | 0x08 | RTAX_GENMASK | 3 | Маска клонирования |
RTA_IFP | 0x10 | RTAX_IFP | 4 | Имя интерфейса |
RTA_IFA | 0x20 | RTAX_IFA | 5 | Адрес интерфейса |
RTA_AUTHOR | 0x40 | RTAX_AUTHOR | 6 | Отправитель запроса на перенаправление |
RTA_BRD | 0x80 | RTAX_BRD | 7 | Адрес получателя типа «точка-точка» или широковещательный |
RTAX_MAX | 8 | Максимальное количество элементов |
В том случае, когда имеется множество структур адреса сокета, они всегда располагаются в порядке, показанном в таблице.
Пример: получение и вывод записи из таблицы маршрутизации
Теперь мы покажем пример использования маршрутизирующих сокетов. Наша программа получает аргумент командной строки, состоящий из адреса IPv4 в точечно-десятичной записи, и отправляет ядру сообщение RTM_GET
для получения этого адреса. Ядро ищет адрес в своей таблице маршрутизации IPv4 и возвращает сообщение RTM_GET
с информацией о соответствующей записи из таблицы маршрутизации. Например, если мы выполним на нашем узле freebsd
такой код
freebsd # getrt 206.168.112.219
dest: 0.0.0.0
gateway: 12.106.32.1
netmask: 0.0.0.0
мы увидим, что этот адрес получателя использует маршрут по умолчанию (который хранится в таблице маршрутизации с IP-адресом получателя 0.0.0.0 и маской 0.0.0.0). Маршрутизатор следующей ретрансляции — это интернет-шлюз нашей системы. Если мы выполним
freebsd # getrt 192.168.42.0
dest: 192.168.42.0
gateway: AF_LINK, index=2
netmask: 255.255.255.0
задав в качестве получателя главную сеть Ethernet, получателем будет сама сеть. Теперь шлюзом является исходящий интерфейс, возвращаемый в качестве структуры sockaddr_dl
с индексом интерфейса 2.
Перед тем как представить исходный код, мы показываем на рис. 18.1, что именно мы пишем в маршрутизирующий сокет и что возвращает ядро.

Рис. 18.2. Структура rti_info, заполненная с помощью нашей функции get_rtaddrs
Затем наша программа проходит массив rti_info
, делая все, что ей нужно, с непустыми указателями массива.
37-44
Каждый из присутствующих четырех возможных адресов выводится. Мы вызываем нашу функцию sock_ntop_host
для вывода адреса получателя и адреса шлюза, но для вывода двух масок подсети вызываем нашу функцию sock_masktop
. Эту новую функцию мы покажем далее.
В листинге 18.5 показана наша функция get_rtaddrs
, которую мы вызывали в листинге 18.4.
Листинг 18.5. Создание массива указателей на структуры адреса сокета в маршрутизирующем сообщении
//libroute/get_rtaddrs.c
1 #include "unproute.h"
2 /*
3 * Округляем 'а' до следующего значения, кратного 'size'
4 */
5 #define ROUNDUP(a, size) (((a) & ((size)-1)) ? (1 + ((a) | ((size)-1))) : (a))
6 /* Переходим к следующей структуре адреса сокета.
7 * Если sa_len равно 0, это значит, что
8 * размер выражен числом типа u_long).
9 */
10 #define NEXT_SA(ap) ар = (SA*) \
11 ((caddr_t)ар + (ap->sa_len ? ROUNDUP(ap->sa_len, sizeof(u_long)) : \
12 sizeof(u_long)))
13 void
14 get_rtaddrs(int addrs, SA *sa, SA **rti_info)
15 {
16 int i;
17 for (i = 0; i
18 if (addrs & (1 sa_data[2];
7 if (sa->sa_len == 0)
8 return ("0.0.0.0");
9 else if (sa->sa_len == 5)
10 snprintf(str, sizeof(str), '"%d.0.0.0", *ptr);
Интервал:
Закладка: