Последний член, используемый для 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() с именем хоста, именем службы, подсказками и в случае невозможности найти соответствие отображается сообщение об ошибке. Если все проходит

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату