Опубликован: 15.06.2004 | Доступ: свободный | Студентов: 2557 / 712 | Оценка: 4.35 / 3.96 | Длительность: 27:47:00
ISBN: 978-5-9556-0011-6
Лекция 11:

Сетевые средства

Опрос данных о сети

Данные о хостах как узлах сети хранятся в сетевой базе, последовательный доступ к которой обслуживается функциями 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 ) задан номером порта, и налагает запрет на обращение к какому-либо сервису имен.

Антон Коновалов
Антон Коновалов

В настоящее время актуальный стандарт - это POSIX 2008 и его дополнение POSIX 1003.13
Планируется ли актуализация материалов данного очень полезного курса?