Троан Эрик В.
Шрифт:
107: case IPPROTO_UDP: printf("\tudp");
108: break;
109: case IPPROTO_RAW: printf("\traw");
110: break;
111: default: printf("\t(%d)
112: addr->ai_protocol);
113: break;
114: }
115: else
116: printf("\t");
117:
118: /* отобразить информацию и для IPv4-, и для IPv6-адресов */
119:
120: if (addr->ai_family == PF_INET) {
121: struct sockaddr_in * inetaddr = (void*)addr->ai_addr;
122: char nameBuf[INET_ADDRSTRLEN];
123:
124: if (serviceName)
125: printf("\tпорт%d", ntohs(inetaddr->sin_port));
126:
127: if (hostName)
128: printf("\tхост%s",
129: inet_ntop(AF_INET, &inetaddr->sin_addr,
130: nameBuf, sizeof(nameBuf)));
131: } else if (addr->ai_family == PF_INET6) {
132: struct sockaddr_in6 * inetaddr =
133: (void*)addr->ai_addr;
134: char nameBuf[INET6_ADDRSTRLEN];
135:
136: if (serviceName)
137: printf("\tпорт%d", ntohs(inetaddr->sin6_port));
138:
139: if (hostName)
140: printf("\tхост%s",
141: inet_ntop(AF_INET6, &inetaddr->sin6_addr,
142: nameBuf, sizeof(nameBuf)));
143: }
144:
145: if (addr->ai_canonname)
146: printf("\tname%s", addr->ai_canonname);
147:
148: printf("\n");
149:
150: addr = addr->ai_next;
151: }
152:
153: /* очистить результаты getaddrinfo */
154: freeaddrinfo(result);
155:
156: return 0;
157: }
В отличие от большинства библиотечных функций,
getaddrinfo
возвращает целое число, которое равно нулю в случае успеха, и описывает ошибку в случае неудачи. Такие функции, как правило, не используют errno
. В табл. 17.3 описаны различные коды ошибок, которые могут возвращать подобные функции. Таблица 17.3. Ошибки поиска соответствия адреса и имени
Ошибка | Описание |
---|---|
EAI_AGAIN | Имя не может быть найдено. Повторный поиск может оказаться успешным. |
EAI_BADFLAGS | В функцию переданы недействительные флаги. |
EAI_FAIL | В процессе поиска соответствия возникла постоянная ошибка. |
EAI_FAMILY | Семейство адресов не распознано. |
EAI_MEMORY | Запрос на выделение памяти не выполнен. |
EAI_NONAME | Имя или адрес невозможно преобразовать. |
EAI_OVERFLOW | Переданный буфер слишком мал. |
EAI_SERVICE | Для данного типа сокета служба не существует. |
EAI_SOCKTYPE | Был передан недействительный тип сокета. |
EAI_SYSTEM | Произошла системная ошибка; сама ошибка содержится в переменной errno . |
Коды ошибок можно преобразовать в строки, описывающие проблему, с помощью функции
gai_strerror
. #include <netdb.h>
const char * gai_strerror(int error);
Здесь параметр
error
должен быть ненулевым значением, возвращенным функцией getaddrinfo
. Если произошла ошибка EAI_SYSTEM
, то для получения более точного описания программа должна использовать strerror(errno)
. 17.5.6. Преобразование адресов в имена
К счастью, переводить IP-адреса и номера портов в имена хостов и служб гораздо проще, чем наоборот.
#include <sys/socket.h>
#include <netdb.h>
int getnameinfo(struct sockaddr * addr, socklen_t addrlen,
char * hostname, size_t hostlen,
char * servicename, size_tservicelen, intflags);
Здесь параметр
addr
указывает либо на struct sockaddr_in
, либо на struct sockaddr_in6
, член addrlen
содержит размер структуры, на которую указывает addr
. IP-адрес и номер порта, определенные addr
, преобразуются в имя хоста, сохраняющееся в ячейке, на которую указывает hostname
, и в имя службы, сохраняющееся в servicename
.