В настоящее время актуальный стандарт - это POSIX 2008 и его дополнение POSIX 1003.13 |
Сетевые средства
Опрос данных о сети
Данные о хостах как узлах сети хранятся в сетевой базе, последовательный доступ к которой обслуживается функциями sethostent(), gethostent() и endhostent() (см. листинг 11.1).
#include <netdb.h> void sethostent (int stayopen); struct hostent *gethostent (void); void endhostent (void);Листинг 11.1. Описание функций последовательного доступа к сетевой базе данных о хостах - узлах сети.
Функция sethostent() устанавливает соединение с базой, остающееся открытым после вызова gethostent(), если значение аргумента stayopen отлично от нуля. Функция gethostent() последовательно читает элементы базы, возвращая результат в структуре типа hostent, содержащей по крайней мере следующие поля.
char *h_name; /* Официальное имя хоста */ char **h_aliases; /* Массив указателей на альтернативные */ /* имена хоста, завершаемый пустым */ /* указателем */ int h_addrtype; /* Тип адреса хоста */ int h_length; /* Длина в байтах адреса данного типа */ char **h_addr_list; /* Массив указателей на сетевые адреса */ /* хоста, завершаемый пустым указателем */
Функция endhostent() закрывает соединение с базой.
В листинге 11.2 показана программа, осуществляющая последовательный просмотр сетевой базы данных о хостах - узлах сети, а в листинге 11.3 приведен фрагмент ее возможной выдачи.
#include <stdio.h> #include <netdb.h> int main (void) { struct hostent *pht; char *pct; int i, j; sethostent (1); while ((pht = gethostent ()) != NULL) { printf ("Официальное имя хоста: %s\n", pht->h_name); printf ("Альтернативные имена:\n"); for (i = 0; (pct = pht->h_aliases [i]) != NULL; i++) { printf (" %s\n", pct); } printf ("Тип адреса хоста: %d\n", pht->h_addrtype); printf ("Длина адреса хоста: %d\n", pht->h_length); printf ("Сетевые адреса хоста:\n"); for (i = 0; (pct = pht->h_addr_list [i]) != NULL; i++) { for (j = 0; j < pht->h_length; j++) { printf (" %d", (unsigned char) pct [j]); } printf ("\n"); } } endhostent (); return 0; }Листинг 11.2. Пример программы, осуществляющей последовательный доступ к сетевой базе данных о хостах - узлах сети.
Официальное имя хоста: localhost Альтернативные имена: Тип адреса хоста: 2 Длина адреса хоста: 4 Сетевые адреса хоста: 127 0 0 1 . . . Официальное имя хоста: t01 Альтернативные имена: niisi.msk.ru t01.niisi.msk.ru mail mailhost loghost server server3 server3.systud.msk.su www www.systud.msk.su t01.systud.msk.su Тип адреса хоста: 2 Длина адреса хоста: 4 Сетевые адреса хоста: 193 232 173 1 . . . Официальное имя хоста: t17 Альтернативные имена: galatenko Тип адреса хоста: 2 Длина адреса хоста: 4 Сетевые адреса хоста: 193 232 173 17 . . .Листинг 11.3. Фрагмент возможных результатов работы программы, осуществляющей последовательный доступ к сетевой базе данных о хостах - узлах сети.
К рассматриваемой базе возможен и случайный доступ по ключам - именам и адресам хостов с помощью функций gethostbyname() и gethostbyaddr(), однако они считаются устаревшими и из новой версии стандарта POSIX могут быть исключены. Вместо них предлагается использовать функции getnameinfo() и getaddrinfo() (см. листинг 11.4).
#include <sys/socket.h> #include <netdb.h> void freeaddrinfo (struct addrinfo *ai); int getaddrinfo (const char *restrict nodename, const char *restrict servname, const struct addrinfo *restrict hints, struct addrinfo **restrict res); int getnameinfo (const struct sockaddr *restrict sa, socklen_t salen, char *restrict node, socklen_t nodelen, char *restrict service, socklen_t servicelen, int flags);Листинг 11.4. Описание функций freeaddrinfo(), getaddrinfo(), getnameinfo().
Функция getaddrinfo() позволяет по имени узла сети (хоста) (аргумент nodename ) и/или имени сетевого сервиса ( servname ) получить набор адресов сокетов и ассоциированную информацию, что дает возможность создать сокет для обращения к заданному сервису.
Если аргумент nodename отличен от пустого указателя, он способен задавать описательное имя или адресную цепочку. Для адресных семейств AF_INET и AF_UNSPEC (см. ниже описание аргумента hints ) именем может служить имя хоста, а адресной цепочкой - стандартные для Internet адреса в точечных обозначениях (например, 193.232.173.17 ).
При пустом значении nodename подразумевается хост, локальный для вызывающего процесса.
Аргумент servname может задавать имя сервиса или (для адресных семейств AF_INET и AF_UNSPEC ) десятичный номер порта. Пустое значение servname означает запрос сетевого адреса.
Аргумент hints позволяет передать дополнительную информацию об опрашиваемом сервисе - адресное семейство, тип сокета, протокол, флаги. Согласно стандарту, структура addrinfo, описанная в заголовочном файле <netdb.h>, должна содержать по крайней мере следующие поля.
int ai_flags; /* Входные флаги */ int ai_family; /* Адресное семейство сокета */ int ai_socktype; /* Тип сокета */ int ai_protocol; /* Протокол сокета */ socklen_t ai_addrlen; /* Длина адреса сокета */ struct sockaddr *ai_addr; /* Адрес сокета */ char *ai_canonname; /* Официальное имя узла сети */ struct addrinfo *ai_next; /* Указатель на следующий элемент списка */
При обращении к функции getaddrinfo() все поля структуры addrinfo, на которую указывает аргумент hints, кроме первых четырех ( ai_flags, ai_family, ai_socktype, ai_protocol ), должны быть нулевыми или равными NULL. Значение AF_UNSPEC в поле ai_family подразумевает, что вызывающего устроит любое адресное семейство. Аналогичный смысл имеют нулевые значения полей ai_socktype и ai_protocol. При hints, равном NULL, подразумевается AF_UNSPEC для ai_family и нулевые значения для других полей.
Из флагов, которые могут быть установлены в поле ai_flags, упомянем следующие.
AI_PASSIVE
Если значение аргумента nodename равно NULL, этот флаг игнорируется. В противном случае, если он указан, будет возвращен адрес сокета, предназначенного для принятия входящих соединений.
AI_CANONNAME
Данный флаг предписывает выяснить официальное имя узла сети.
AI_NUMERICHOST
Флаг означает, что хост задан адресной цепочкой, и не допускает использования какого-либо сервиса имен.
AI_NUMERICSERV
Флаг помечает, что сервис (аргумент servname ) задан номером порта, и налагает запрет на обращение к какому-либо сервису имен.