Последний член, используемый для hints — это aflags, который принимает одно или несколько (объединенных логическим 'ИЛИ') из перечисленных ниже значений.
AI_ADDRCONFIG
По умолчанию функция getaddrinfo() возвращает все адреса, соответствующие запросу. Данный флаг указывает на возврат адресов только тех протоколов, чьи адреса сконфигурированы в локальной системе. Другими словами, она возвращает только IPv4-адреса в системах с IPv4-интерфейсами и только IPv6-адреса в системах с интерфейсами IPv6.
AI_CANONNAME
При возврате поле ai_canonname содержит каноническое имя хоста для адреса, указанного в struct addrinfo. Поиск этого адреса сопровождается дополнительными поисками в службе DNS и, как правило, не является необходимым.
AI_NUMERICHOST
Параметр hostname должен представлять собой адрес в форме с разделительными запятыми или двоеточиями. Никакие преобразования имени хоста не выполняются. Это предохраняет getaddrinfo() от каких-либо поисков имени хоста, которые могут оказаться весьма длительным процессом.
AI_PASSIVE
Если hostname равен NULL и присутствует этот флаг, то возвращается неустановленный адрес, который позволяет ожидать соединений на всех интерфейсах. Если данный флаг не указан (а значение hostname равно NULL), возвращается адрес обратной связи[135].
Последний параметр res в getaddrinfo() должен быть адресом указателя на struct addrinfo. Для успешного завершения переменная, на которую указывает res, устанавливается на первую запись в односвязном списке адресов, который соответствует запросу. Член ai_next структуры struct addrinfo указывает на следующий член связного списка, и для последнего узла в списке параметр ai_next равен NULL.
Когда приложение завершает работу с возвращенным связным списком, функция freeaddrinfo() освобождает память, занимаемую списком.
#include <sys/types.h>
#include <socket.h>
#include <netdb.h>
void freeaddrinfo(struct addrinfo * res);
Единственным параметром для freeaddrinfo является указатель на первый узел в списке.
Каждый узел в возвращаемом списке имеет тип struct addrinfo и специфицирует один адрес, соответствующий запросу. Каждый адрес содержит не только IPv4- или IPv6-адрес, он также определяет тип соединения (например, дейтаграмма) и протокол (такой как UDP). Если для одного IP- адреса в запросе подходит несколько типов соединений, то данный адрес включается в несколько узлов.
Каждый узел содержит описанную ниже информацию.
• ai_family — семейство протоколов (PF_INET или PF_INET6), к которому принадлежит адрес.
• ai_socktype — тип соединения для адреса (как правило, принимает одно из значений SOCK_STREAM, SOCK_DGRAM или SOCK_RAW).
• ai_protocol — протокол для адреса (обычно IPPROTO_TCP или IPPROTO_UDP).
• Если в параметре hints был указан флаг AI_CANONNAME, то ai_canonname содержит каноническое имя для адреса.
• ai_addr указывает на struct sockaddr для соответствующего протокола. Например, если ai_family принимает значение PF_INET, то ai_addr указывает на struct sockaddr_in. Член ai_addrlen определяет длину структуры, на которую указывает ai_addr.
• Если предусмотрен параметр servicename, то в качестве номера порта в каждом адресе устанавливается официальный порт данной службы. В противном случае номер порта для каждого адреса равен нулю.
• Если не был передан параметр hostname, то номера портов устанавливаются для каждого адреса, однако в качестве IP-адреса определяется или адрес обратной связи, или неустановленный адрес (как указывалось ранее в описании флага AI_PASSIVE).
Все это может показаться достаточно запутанным. На самом деле, существует только два различных способа стандартного применения функции getaddrinfo(). Большинство клиентских программ стремятся превратить имя хоста, передаваемое пользователем, и имя службы, известное программе, в полностью определенный адрес, с которым пользователь может установить соединение. Достичь этой цели нетрудно. Ниже приводится программа, которая принимает имя хоста как первый аргумент и имя службы как второй, после чего выполняет все необходимые преобразования.
1: /* clientlookup.c */
2:
3: #include <netdb.h>
4: #include <stdio.h>
5: #include <string.h>
6:
7: int main(int argc, const char ** argv) {
8: struct addrinfo hints, * addr;
9: const char * host = argv[1], * service = argv[2];
10: int rc;
11:
12: if (argc != 3) {
13: fprintf(stderr, 'требуется в точности два аргумента
');
14: return 1;
15: }
16:
17: memset(&hints, 0, sizeof(hints));
18:
19: hints.ai_socktype = SOCK_STREAM;
20: hints.ai_flags = AI_ADDRCONFIG;
21: if ((rc = getaddrinfo(host, service, &hints, &addr)))
22: fprintf(stderr, 'сбой поиска
');
23: else
24: freeaddrinfo(addr);
25:
26: return 0;
27: }
Давайте обратим внимание на строки 17–24 этой программы. После очистки структуры hints приложение запрашивает адреса SOCK_STREAM, которые используют протокол, сконфигурированный на локальной системе (путем установки флага AI_ADDRCONFIG). Затем активизируется функция getaddrinfo() с именем хоста, именем службы, подсказками и в случае невозможности найти соответствие отображается сообщение об ошибке. Если все проходит
