Уильям Стивенс - UNIX: разработка сетевых приложений
- Название:UNIX: разработка сетевых приложений
- Автор:
- Жанр:
- Издательство:Питер
- Год:2007
- Город:Санкт-Петербург
- ISBN:5-94723-991-4
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Уильям Стивенс - UNIX: разработка сетевых приложений краткое содержание
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
UNIX: разработка сетевых приложений - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
■ Типичный сервер задает службу (service), но не имя узла (hostname), и задает флаг AI_PASSIVEв структуре hints. Возвращаемая структура адреса сокета должна содержать IP-адрес, равный INADDR_ANY(для IPv4) или IN6ADDR_ANY_INIT(для IPv6). Сервер TCP затем вызывает функции socket, bindи listen. Если сервер хочет разместить в памяти с помощью функции mallocдругую структуру адреса сокета, чтобы получить адрес клиента из функции accept, то возвращаемое значение ai_addrlenзадает требуемый для этого размер.
Сервер UDP вызовет функции socket, bindи затем recvfrom. Если сервер хочет разместить в памяти с помощью функции mallocдругую структуру адреса сокета, чтобы получить адрес клиента из функции recvfrom, возвращаемое значение ai_addrlenтакже задает нужный размер.
Как и в случае типичного клиентского кода, если сервер знает, что он обрабатывает только один тип сокета, то элемент ai_socktypeструктуры hintsдолжен быть задан либо как SOCK_STREAM, либо как SOCK_DGRAM. Это позволяет избежать возвращения множества структур, с (возможно) неверным значением элемента ai_socktype.
■ До сих пор мы демонстрировали серверы TCP, создающие один прослушиваемый сокет, и серверы UDP, создающие один сокет дейтаграмм. Это тот вариант, который подразумевался в предыдущем абзаце. Альтернативным устройством является сервер, который обрабатывает множество сокетов с помощью функции select. В этом сценарии сервер должен последовательно перебрать все структуры из списка, возвращаемого функцией getaddrinfo, создать по одному сокету для каждой структуры и вызвать функцию select.
Проблема этой технологии состоит в том, что условие, по которому функция getaddrinfo возвращает множество структур, возникает, когда служба может обрабатываться как протоколом IPv4, так и протоколом IPv6 (см. табл. 11.3). Но эти два протокола не полностью независимы, как мы увидели в разделе 10.2, то есть если мы создаем прослушиваемый сокет IPv6 для данного порта, нет необходимости создавать для него прослушиваемый сокет IPv4, поскольку соединения, приходящие от клиентов IPv4, автоматически обрабатываются стеком протоколов и прослушиваемым сокетом IPv6, при условии, что параметр сокета IPV6_V6ONLY не установлен.
Невзирая на тот факт, что функция getaddrinfo«лучше», чем функции gethostbynameи gethostbyaddr(помимо того что эта функция упрощает написание кода, не зависящего от протокола, она обрабатывает и имя узла, и имя службы, и к тому же вся возвращаемая ею информация размещается в памяти динамически, а не статически), ее все же не так просто использовать, как это могло показаться. Проблема в том, что нам требуется разместить в памяти структуру hints, инициализировать ее нулем, заполнить необходимые поля, вызвать функцию getaddrinfoи затем пройти весь связный список, проверяя каждый его элемент. В последующих разделах мы предоставим более простые интерфейсы для типичных клиентов TCP и UDP и серверов, которые будем создавать в оставшейся части книги.
Функция getaddrinfoрешает проблему преобразования имен узлов и имен служб в структуры адресов сокетов. В разделе 11.17 мы опишем обратную функцию getnameinfo, которая преобразует структуры адресов сокетов в имена узлов и имена служб.
11.7. Функция gai_strerror
Ненулевые значения ошибок, возвращаемых функцией getaddrinfo, имеют названия и значения, показанные в табл. 11.2. Функция gai_strerrorполучает одно из этих значений в качестве аргумента и возвращает указатель на соответствующую текстовую строку с описанием ошибки.
#include
char *gai_strerror(int error );
Возвращает: указатель на строку с описанием ошибки
Таблица 11.2. Ненулевые возвращаемые значения (константы) ошибок функции getaddrinfo
| Константа | Описание |
|---|---|
| EAI_AGAIN | Временный сбой при попытке разрешения имен |
| EAI_BADFLAGS | Недопустимое значение ai_flags |
| EAI_FAIL | Неисправимая ошибка при разрешении имен |
| EAI_FAMILY | Семейство ai_family не поддерживается |
| EAI_MEMORY | Ошибка при выделении памяти |
| EAI_NONAME | Имя узла или имя службы неизвестны или равны NULL |
| EAI_OVERFLOW | Переполнен буфер пользовательских аргументов (только для getnameinfo) |
| EAI_SERVICE | Запрошенная служба не поддерживается для данного типа сокета ai_socktype |
| EAI_SOCKTYPE | Тип сокета ai_socktype не поддерживается |
| EAI_SYSTEM | Другая системная ошибка, возвращаемая в переменной errno |
11.8. Функция freeaddrinfo
Вся память, занимаемая структурами addrinfo, структурами ai_addrи строкой ai_canonname, которые возвращаются функцией getaddrinfo, динамически выделяется функцией malloc. Эта память освобождается при вызове функции freeaddrinfo.
#include
void freeaddrinfo(struct addrinfo * ai );
Переменная aiдолжна указывать на первую из структур addrinfo, возвращаемых функцией getaddrinfo. Освобождается вся область памяти, занятая структурами из связного списка, вместе с динамически выделенной областью памяти, содержащей данные, на которые указывают эти структуры (например, структуры адресов сокетов и канонические имена узлов).
Предположим, что мы вызываем функцию getaddrinfo, проходим последовательно по всему связному списку структур addrinfoи находим нужную структуру. Если далее мы попытаемся сохранить нужную нам информацию простым копированием структуры addrinfo, а затем вызовем функцию freeaddrinfo, мы получим скрытую ошибку. Причина в том, что структура addrinfoсама указывает на динамически выделенный участок памяти (для структуры адреса сокета и, возможно, для канонического имени). Но эта область памяти, на которую указывает сохраненная нами структура, при вызове функции freeaddrinfoосвобождается и может использоваться для хранения какой-либо иной информации.
Создание копии только самой структуры addrinfo, а не структур, на которые она, в свою очередь, указывает, называется поверхностным копированием (shallow сору). Копирование структуры addrinfo и всех структур, на которые она указывает, называется детальным копированием (deep сору).
11.9. Функция getaddrinfo: IPv6
Стандарт POSIX определяет как getaddrinfo, так и возвращаемые этой функцией данные для протоколов IPv4 и IPv6. Отметим следующие моменты, прежде чем свести возвращаемые значения воедино в табл. 11.3.
■ Входные данные функции getaddrinfoмогут относиться к двум различным типам, которые выбираются в зависимости от того, какой тип структуры адреса сокета вызывающий процесс хочет получить обратно и какой тип записей нужно искать в DNS или иной базе данных.
Интервал:
Закладка: