Майкл Джонсон - Разработка приложений в среде Linux. Второе издание
- Название:Разработка приложений в среде Linux. Второе издание
- Автор:
- Жанр:
- Издательство:Вильямс
- Год:2007
- Город:Москва
- ISBN:978-5-8459-1143-8
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Майкл Джонсон - Разработка приложений в среде Linux. Второе издание краткое содержание
Книга известных профессионалов в области разработки коммерческих приложений в Linux представляет собой отличный справочник для широкого круга программистов в Linux, а также тех разработчиков на языке С, которые перешли в среду Linux из других операционных систем. Подробно рассматриваются концепции, лежащие в основе процесса создания системных приложений, а также разнообразные доступные инструменты и библиотеки. Среди рассматриваемых в книге вопросов можно выделить анализ особенностей применения лицензий GNU, использование свободно распространяемых компиляторов и библиотек, системное программирование для Linux, а также написание и отладка собственных переносимых библиотек. Изобилие хорошо документированных примеров кода помогает лучше усвоить особенности программирования в Linux.
Книга рассчитана на разработчиков разной квалификации, а также может быть полезна для студентов и преподавателей соответствующих специальностей.
Разработка приложений в среде Linux. Второе издание - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
В данный момент действует множество библиотечных функций, относящихся к работе сетей TCP/IP, которые нельзя применять в новых приложениях. Однако они широко используются в существующих IPv4-программах. В связи с этим они рассматриваются ниже для того, чтобы помочь вам понять и обновить старые коды.
17.8.1. Манипулирование IPv4-адресами
Функции inet_ntop()
и inet_pton()
являются относительно новыми и были введены для того, чтобы один набор функций мог обрабатывать и IPv4-, и IPv6-адреса. До их появления в программах использовались функции inet_addr()
, inet_aton()
и inet_ntoa()
, которые предназначены только для IPv4.
Вспомните, что struct sockaddr_in
определяется следующим образом
struct sockaddr__in {
short int sin_family; /* AF_INET */
unsigned short int sin_port; /* номер порта */
struct in_addr sin_addr; /* IP-адрес */
}
Член sin_addr
представляет собой структуру struct in_addr
; унаследованные функции используют его в качестве параметра [145] Применение этой структуры делает невозможным расширение данных функций на IPv6 без изменения их интерфейса.
. Подразумевается, что данная структура является непрозрачной; программы приложений могут обрабатывать struct in_addr
исключительно через библиотечные функции. Старой функцией для преобразования IPv4-адреса в десятичную форму с разделительными точками служит inet_ntoa()
.
#include
#include
char * inet_ntoa(struct in_addr address);
Передаваемый адрес преобразуется в строку в десятичном формате с разделительными точками, возвращается указатель на данную строку. Строка сохраняется в статическом буфере библиотеки С и уничтожается при следующем вызове inet_ntoa()
[146] Функции, использующие статическую память для сохранения результатов, усложняют построение многопоточных приложений, поскольку в код приложения требуется добавлять блокировки для защиты этих статических буферов.
.
Существуют две функции, которые предлагают обратное преобразование десятичной строки в двоичный IP-адрес. Более старая из них функция inet_addr()
имеет две проблемы, обе вызванные тем, что она возвращает результат типа long
. Она не возвращает struct in_addr
, как предполагается остальными стандартными функциями, поэтому программисты были вынуждены выполнять неуклюжие приведения. К тому же, если переменная типа long
имела 32 бита, то программы не могли различить возврат числа -1 (что указывает на ошибку, например, неправильный адрес) и двоичного представления адреса 255.255.255.255.
#include
#include
unsigned long int inet_addr(const char * ddaddress);
Функция принимает передаваемую строку, которая должна содержать десятичный IP-адрес с разделительными точками, и преобразует ее в двоичный IP-адрес.
Для исправления недостатков inet_addr()
была введена функция inet_aton()
.
#include
#include
int inet_aton(const char * ddaddress, struct in_addr * address);
Данная функция ожидает строку, содержащую десятичный IP-адрес, и размещает двоичное представление этого адреса в структуре struct in_addr
, на которую указывает параметр address
. В отличие от большинства библиотечных функций inet_aton()
возвращает нуль в случае ошибки и ненулевое значение, если преобразование прошло успешно.
17.8.2. Преобразование имен хостов
Функции getaddrinfo()
, getnameinfo()
, позволяющие легко создавать программы, которые поддерживают и IPv4, и IPv6, были введены именно с этой целью. Исходные функции имен хостов было сложно расширить на IPv6, их интерфейсы требовали, чтобы приложения учитывали множество особенностей версии в структурах, сохраняющих IP-адрес. Новые интерфейсы абстрактны, поэтому поддерживают IPv4 и IPv6 одинаково.
Вместо того чтобы возвращать связный список, как это делает getaddrinfo()
, старые функции имен хостов используют struct hostent
, которая может содержать все имена хостов и адреса для одного хоста.
#include
struct hostent {
char* h_name; /* каноническое имя хоста */
char** h_aliases; /* псевдонимы (завершающиеся NULL) */
int h_addrtype; /* тип адреса хоста */
int h_length; /* длина адреса */
char** h_addr_list; /* список адресов (завершающийся NULL) */
};
Здесь h_name
— каноническое имя хоста. Массив h_aliases
содержит все псевдонимы данного хоста. Последняя запись в h_aliases
— это указатель NULL, сигнализирующий о конце массива.
Параметр h_addrtype
сообщает тип адреса хоста. В данной главе будет применяться только AF_INET
. Приложения, которые создавались для поддержки IPv6, получат и другие типы адресов [147] Наверное, не существует IPv6-программ, использующих struct hostaddr , однако они могут это делать. Функции, которые мы обсуждаем здесь, по умолчанию возвращают только информацию IPv4. Мы не будем рассматривать применение этих функций с IPv6.
. Следующий член h_length
указывает длину двоичных адресов для данного хоста. Для адресов AF_INET
эта длина равна sizeof(struct in_addr)
. Последний элемент h_addr_list
представляет собой массив указателей на адреса данного хоста, последний из которых равен NULL
для обозначения конца списка. Если h_addrtype
равен AF_INET
, то каждый указатель в этом списке указывает на структуру struct in_addr
.
Две библиотечные функции выполняют преобразования между IP-номерами и именами хостов. Первая из них gethostbyname()
возвращает struct hostent
для имени хоста. Вторая — gethostbyaddr()
— возвращает информацию о машине с данным IP-адресом.
#include
struct hostent * gethostbyname(const char * name);
struct hostent * gethostbyaddr(const char * addr, int len, int type);
Обе функции возвращают указатель на struct hostent
. Структура может быть перезаписана при последующем вызове одной из функций, поэтому все значения, которые могут понадобиться позже, программа должна сохранять.
Функция gethostbyname()
принимает один параметр — строку, содержащую имя хоста. Функция gethostbyaddr()
принимает три параметра, которые вместе определяют адрес. Первый из них addr
указывает на struct in_addr
. Следующий len
устанавливает длину информации, на которую указывает параметр addr
. Последний type
излагает тип адреса, который нужно преобразовать в имя хоста ( AF_INET
для IPv4-адресов).
Если во время поиска имени хоста происходят ошибки, то код ошибки передается в h_errno
. Вызов функции herror()
распечатывает описание ошибки (данная функция почти идентична стандартной функции perror()
).
Единственный код ошибки, на котором тестируется большинство программ, это NETDB_INTERNAL
, который указывает на неудачный системный вызов. При возвращении этой ошибки параметр errno содержит описание той проблемы, которая привела к отказу.
Интервал:
Закладка: