UNIX: разработка сетевых приложений
2. Если служба предоставляется для множества типов сокетов, то одна структура может быть возвращена для каждого типа сокета в зависимости от
. (Заметьте, что большинство реализацийai_socktypeсчитают, что номер порта используется только тем типом сокета, который запрашивается вgetaddrinfo. Если аргументai_socktypeне определен, функция возвращает ошибку.)ai_socktypeНапример, если структура
пуста, а вы запрашиваете записи для службыhintsна узле с двумя IP-адресами, возвращаются четыре структурыdomain:addrinfo■ одна для первого IP-адреса и типа сокета SOCK_STREAM;
■ одна для первого IP-адреса и типа сокета SOCK_DGRAM;
■ одна для второго IP-адреса и типа сокета SOCK_STREAM;
■ одна для второго IP-адреса и типа сокета SOCK_DGRAM.
Мы показываем схематическое изображение этого примера на рис. 11.3. Не существует никакого гарантированного порядка структур при возвращении множества элементов. Например, мы не можем считать, что службы TCP возвращаются перед службами UDP.
Рис. 11.3. Пример информации, возвращаемой функцией getaddrinfo
ПРИМЕЧАНИЕХотя это и не гарантируется, реализация должна возвращать IP-адреса в том же порядке, в котором они возвращаются DNS. Некоторые распознаватели позволяют администратору указывать порядок сортировки адресов в файле /etc/resolv.conf. Протокол IPv6 определяет правила выбора адресов (RFC 3484 [28]), которые могут влиять на порядок адресов, возвращаемых getaddrinfo.
Информация, возвращаемая в структурах
, готова для передачи функциямaddrinfoиsocketилиconnect(для клиента) иsendto(для сервера). Аргументы функцииbind— это элементыsocket,ai_familyиai_socktype. Второй и третий аргументы функцийai_protocolиconnect— это элементыbind(указатель на структуру адреса сокета соответствующего типа, заполняемую функциейai_addr) иgetaddrinfo(длина этой структуры адреса сокета).ai_addrlenЕсли в структуре
установлен флагhints, элементAI_CANONNAMEпервой возвращаемой структуры указывает на каноническое имя узла. В терминах DNS это обычно полное доменное имя (FQDN). Программы типаai_canonnameшироко используют этот флаг для того, чтобы выводить канонические имена систем, к которым производится подключение. Пользователь может указать короткое имя узла или его альтернативное имя, но он должен знать, с какой системой он в результате соединился.telnetНа рис. 11.3 представлена возвращаемая информация для следующего вызова:
struct addrinfo hints, *res;bzero(&hints, sizeof(hints));hints.ai_flags = AI_CANONNAME;hints.ai_family = AF_INET;getaddrinfo("bsdi", "domain", &hints, &res);На этом рисунке все, кроме переменной
, относится к динамически выделяемой памяти (например, с помощью функцииres). Предполагается, что каноническое имя узлаmalloc—freebsd4, и что этот узел имеет два адреса IPv4 в DNS.freebsd4.unpbook.comПорт 53 предназначен для службы
, и нужно учитывать, что этот номер порта будет представлен в структурах адресов сокетов в сетевом порядке байтов. Мы приводим возвращаемые значенияdomainIPPROTO_TCP и IPPROTO_UDP. Функцияai_protocolможет возвращать значениеgetaddrinfoравное 0 для структур SOCK_STREAM, если этого достаточно для однозначного определения протокола (типа сокета недостаточно, например, если в системе помимо TCP реализован и SCTP), и 0 для структур SOCK_DGRAM, если в системе не реализованы другие протоколы дейтаграмм для IP (на момент написания этой книги стандартизованных протоколов еще не было, но два уже разрабатывались IETF). Лучше всего, еслиai_protocolвсегда будет возвращать конкретный тип протокола.getaddrinfoВ табл. 11.1 показано число структур
для каждого возвращаемого адреса, определяемое на основе заданного имени службы (которое может быть представлено десятичным номером порта) и рекомендацииaddrinfo.ai_socktypeТаблица 11.1. Число структур addrinfo, возвращаемых для каждого IP-адреса
Элемент ai_socktype Служба обозначена именем и предоставляется: Служба обозначена именем порта Только TCP Только UDP Только SCTP TCP и UDP TCP и SCTP TCP, UDP и SCTP 0 1 1 1 2 2 3 Ошибка SOCK_STREAM 1 Ошибка 1 1 2 2 2 SOCK_DGRAM Ошибка 1 1 Ошибка 1 1 SOCK_SEQPACKET Ошибка Ошибка 1 Ошибка 1 1 1 Более одной структуры
возвращается для каждого IP-адреса только в том случае, когда полеaddrinfoструктурыai_socktypeпусто и либо служба поддерживается TCP и UDP (как указано в файлеhints), либо задан номер порта для этой службы./etc/services
