Майкл Джонсон - Разработка приложений в среде Linux. Второе издание
- Название:Разработка приложений в среде Linux. Второе издание
- Автор:
- Жанр:
- Издательство:Вильямс
- Год:2007
- Город:Москва
- ISBN:978-5-8459-1143-8
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Майкл Джонсон - Разработка приложений в среде Linux. Второе издание краткое содержание
Книга известных профессионалов в области разработки коммерческих приложений в Linux представляет собой отличный справочник для широкого круга программистов в Linux, а также тех разработчиков на языке С, которые перешли в среду Linux из других операционных систем. Подробно рассматриваются концепции, лежащие в основе процесса создания системных приложений, а также разнообразные доступные инструменты и библиотеки. Среди рассматриваемых в книге вопросов можно выделить анализ особенностей применения лицензий GNU, использование свободно распространяемых компиляторов и библиотек, системное программирование для Linux, а также написание и отладка собственных переносимых библиотек. Изобилие хорошо документированных примеров кода помогает лучше усвоить особенности программирования в Linux.
Книга рассчитана на разработчиков разной квалификации, а также может быть полезна для студентов и преподавателей соответствующих специальностей.
Разработка приложений в среде Linux. Второе издание - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
INET_ADDRSTRLEN
является константой, определяющей наибольший размер dest
, необходимый для хранения любого IPv4-адреса. Соответственно, INET6_ADDRSTRLEN
определяет максимальный размер массива для IPv6-адреса.
Программа-пример netlookup.с
демонстрирует использование inet_ntop()
; полная программа представлена далее в этой главе.
120: if (addr->ai_family == PF_INET) {
121: struct sockaddr_in * inetaddr = (void*)addr->ai_addr;
122: char nameBuf[INET_ADDRSTRLEN];
123:
124: if (serviceName)
125: printf("\tport %d", ntohs(inetaddr->sin_port));
126:
127: if (hostName)
128: printf("\thost %s",
129: inet_ntop(AF_INET, &inetaddr->sin_addr,
130: nameBuf, sizeof(nameBuf)));
131: } else if (addr->ai_family == PF_INET6) {
132: struct sockaddr_in6 *inetaddr =
133: (void *) addr->ai_addr;
134: char nameBuf[INET6_ADDRSTRLEN];
135:
136: if (serviceName)
137: printf("\tport %d", ntohs(inetaddr->sin6_port));
138:
139: if (hostName)
140: printf("\thost %s",
141: inet_ntop(AF_INET6, &inetaddr->sin6_addr,
142: nameBuf, sizeof(nameBuf)));
143: }
Обратное преобразование строки, содержащей адрес с точками или двоеточиями, в двоичный IP-адрес выполняет функция inet_pton()
.
#include
int inet_pton(int family, const char * address, void * dest);
Параметр family
определяет тип преобразуемого адреса (либо AF_INET
, либо AF_INET6
), a address
указывает на строку, в которой содержится символьное представление адреса. Если используется AF_INET
, то десятичная строка с точками преобразуется в двоичный адрес, хранящийся в переменной, на которую указывает параметр dest
структуры struct in_addr
. Для AF_INET6
строка с двоеточиями преобразуется и сохраняется в переменной, на которую указывает dest
структуры struct in6_addr
. В отличие от большинства библиотечных функций, inet_pton()
возвращает 1
, если преобразование прошло успешно, 0
, если dest
не содержит соответствующий адрес, и -1
, если параметр family
не совпадает с AF_INET
или AF_INET6
.
Программа-пример reverselookup
, код которой представлен далее в главе, использует функцию inet_pton()
для преобразования IPv4- и IPv6-адресов, передаваемых пользователем, в структуры struct sockaddr
. Ниже приводится раздел кода, выполняющий преобразования IP-адреса, на который указывает hostAddress
. В конце данного кода struct sockaddr * addr
указывает на структуру, содержащую преобразованный адрес.
79: if (!hostAddress) {
80: addr4.sin_family = AF_INET;
81: addr4.sin_port = portNum;
82: } else if (! strchr(hostAddress, ':')) {
83: /* Если в hostAddress появляется двоеточие, то принимаем версию IPv6.
84: В противном случае это IPv4-адрес */
85:
86: if (inet_pton(AF_INET, hostAddress,
87: &addr4.sin_addr) <= 0) {
88: fprintf(stderr, "ошибка преобразования IPv4-адреса %s\n",
89: hostAddress);
90: return 1;
91: }
92:
93: addr4.sin_family = AF_INET;
94: addr4.sin_port = portNum;
95: } else {
96:
97: memset(&addr6, 0, sizeof(addr6));
98:
99: if (inet_pton(AF_INET6, hostAddress,
100: &addr6.sin6_addr) <= 0) {
101: fprintf(stderr, "ошибка преобразования IPv6-адреса %s\n",
102: hostAddress);
103: return 1;
104: }
105:
106: addr6.sin6_family = AF_INET6;
107: addr6.sin6_port = portNum;
108: addr = (struct sockaddr *) &addr6;
109: addrLen = sizeof(addr6);
110: }
17.5.5. Преобразование имен в адреса
Длинные последовательности чисел являются отлично подходящим методом идентификации для компьютеров, позволяющим им однозначно узнавать друг друга. Однако большинство людей охватывает ужас при мысли о том, что придется иметь дело с большим количеством цифр. Для того чтобы разрешить людям применять текстовые названия для компьютеров вместо числовых, в состав протоколов TCP/IP входит распределенная база данных для взаимных преобразований имен хостов и IP-адресов. Эта база данных называется DNS(Domain Name System — служба имен доменов), она подробно рассматривается в [34] и [1].
Служба DNS предлагает много функций, но сейчас нас интересует одна — возможность преобразования IP-адресов в имена хостов и наоборот. Несмотря на то что это преобразование должно выполняться как однозначное соответствие, на самом деле оно представляет собой отношение типа "многие ко многим". Другими словами, каждый IP-адрес может соответствовать нулю или более именам хостов, а каждое имя хоста соответствует нулю или более IP-адресам.
Использование неоднозначного соответствия между именами хостов и IP-адресами может показаться странным. Однако многие Internet-сайты применяют одну и ту же машину для ftp-сайта и Web-сайта. При этом адреса www.some.org
и ftp.some.org
должны ссылаться на одну и ту же машину, а для одной машины не нужны два IP-адреса. Таким образом, два имени хостов сводятся к одному IP-адресу. Каждый IP-адрес имеет одно первичное, или каноническое имя хоста, которое используется, если IP-адрес требуется преобразовать в единственное имя хоста во время обратного поиска имен.
Наиболее распространенной причиной, по которой одному имени хоста ставится в соответствие несколько IP-адресов, является балансировка нагрузки. Серверы имен (программы, предлагающие преобразование имен хостов в IP-адреса) часто конфигурируются так, что возвращают в разное время разные адреса для одного и того же имени. Это позволяет нескольким физическим машинам поддерживать единую службу.
Появление IPv6 повлекло за собой еще одну причину, по которой одно имя хоста должно иметь несколько адресов. Многие машины сейчас имеют одновременно и IPv4-, и IPv6-адреса.
Библиотечная функция getaddrinfo()
[134] Если у вас большой опыт в программировании сокетов (или вы сравниваете данную книгу с ее первым изданием), то вы обязательно заметите, что функции, применявшиеся для преобразования имен, значительно изменились. Эти изменения позволяют создавать программы абсолютно независимо от того протокола, который они используют. Теперь гораздо легче разрабатывать программы, работающие как на IPv4-, так и на IPv6-машинах. Они также должны распространяться на остальные протоколы, хотя функция getaddrinfo() в данный момент работает только для IPv4 и IPv6.
предлагает программам простой доступ к преобразованиям имен хостов DNS.
#include
#include
#include
int getaddrinfo(const char * hostname, const char * servicename,
const struct addrinfo * hints, struct addrinfo ** res);
Концепция этой функции достаточно простая, однако весьма мощная, в связи с этим ее описание может показаться несколько запутанным. Идея заключается в том, что функция принимает имя хоста, имя службы (или оба из них) и превращает их в список IP-адресов. Затем с использованием hints
список фильтруется и те адреса, которые не нужны приложению, отбрасываются. Окончательный список возвращается в виде связного списка в переменной res
.
Интервал:
Закладка: