Чтение онлайн

ЖАНРЫ

Основы программирования в Linux
Шрифт:

tcp 1 0 localhost:9734 localhost:1175 TIME_WAIT root

Примечание

Если вы пользуетесь компьютером, у которого собственный формат представления целых совпадает с сетевым порядком следования байтов, вы не увидите никакой разницы. Но для обеспечения корректного взаимодействия клиентов и серверов с разной архитектурой важно всегда применять функции преобразования.

Сетевая информация

До сих пор у клиентских и серверных программ были адреса и номера портов, компилируемые в них. В более универсальных серверных и клиентских

программах для определения применяемых адресов и портов вы можете использовать данные сети.

Если у вас есть на это право, можно добавить свой сервер к списку известных сервисов в файл /etc/services, который назначает имена номерам портов, так что клиенты могут использовать вместо номеров символические имена сервисов.

Точно так же зная имя компьютера, можно определить IP-адрес, вызвав функции базы данных сетевых узлов (host database), которые найдут эти адреса. Делают они это, обращаясь за справкой к конфигурационным файлам, например, etc/hosts или к сетевым информационным сервисам, таким как NIS (Network Information Services (сервисы сетевой информации), ранее известным как Yellow Pages (желтые страницы)) и DNS (Domain Name Service, служба доменных имен).

Функции базы данных сетевых узлов или хостов (Host database) объявлены в заголовочном файле интерфейса netdb.h:

#include <netdb.h>

struct hostent *gethostbyaddr(const void* addr, size_t len, int type);

struct hostent* gethostbyname(const char* name);

Структура, возвращаемая этими функциями, должна как минимум содержать следующие элементы.

struct hostent {

 char *h_name; /* Имя узла */

 char **h_aliases; /* Перечень псевдонимов (nicknames) */

 int h_addrtype; /* Тип адреса */

 int h_length; /* Длина адреса в байтах */

 char **h_addr_list /* Перечень адреса (сетевой порядок байтов) */

};

Если в базе данных нет элемента, соответствующего заданному узлу или адресу, информационные функции вернут пустой указатель.

Аналогично информацию, касающуюся сервисов и связанных номеров портов, можно получить с помощью информационных функций сервисов:

#include <netdb.h>

struct servent *getservbyname(const char *name, const char *proto);

struct servent *getservbyport(int port, const char *proto);

Параметр

proto
задает протокол, который будет применяться для подключения к сервису, либо "tcp" для TCP-соединений типа
SOCK_STREAM
, либо "udp" для UDP-дейтаграмм типа
SOCK_DGRAM
.

Структура

servent
содержит как минимум следующие элементы:

struct servent {

 char *s_name; /* Имя сервиса */

 char **s_aliases; /* Список псевдонимов (дополнительных имен) */

 int s_port; /* Номер IP-порта */

 char *s_proto; /*
Тип сервиса, обычно "tcp" или "udp" */

}

Вы можете собрать воедино информацию о компьютере из базы данных сетевых узлов, вызвав функцию

gethostbyname
и выведя ее результаты. Учтите, что адрес необходимо преобразовать в соответствующий тип и перейти от сетевого упорядочивания к пригодной для вывода строке с помощью преобразования
inet_ntoa
, определенного следующим образом:

#include <arpa/inet.h>

char *inet_ntoa(struct in_addr in);

Функция преобразует адрес интернет-узла в строку формата четверки чисел с точками. В случае ошибки она возвращает -1, но в стандарте POSIX не определены конкретные ошибки. Еще одна новая функция, которую вы примените, —

gethostname
:

#include <unistd.h>

int gethostname(char *name, int name length);

Эта функция записывает имя текущего узла в строку, заданную параметром

name
. Имя узла будет нуль-терминированной строкой. Аргумент
namelength
содержит длину строкового имени и, если возвращаемое имя узла превысит эту длину, оно будет обрезано. Функция
gethostname
возвращает 0 в случае успешного завершения и -1 в случае ошибки. И снова ошибки в стандарте POSIX не определены.

Выполните упражнение 15.5.

Упражнение 15.5. Сетевая информация

Данная программа getname.c получает сведения о компьютере.

1. Как обычно, вставьте соответствующие заголовочные файлы и объявите переменные:

#include <netinet/in.h>

#include <arpa/inet.h>

#include <unistd.h>

#include <netdb.h>

#include <stdio.h>

#include <stdlib.h>

int main(int argc, char *argv[]) {

 char *host, **names, **addrs;

 struct hostent *hostinfo;

2. Присвойте переменной

host
значение аргумента, предоставляемого при вызове программы
getname
, или по умолчанию имя машины пользователя:

 if (argc == 1) {

char myname[256];

gethostname(myname, 255);

host = myname;

 } else host = argv[1];

3. Вызовите функцию gethostbyname и сообщите об ошибке, если никакая информация не найдена:

 hostinfo = gethostbyname(host);

 if (!hostinfo) {

fprintf(stderr, "cannot get info for host: %s\n", host);

exit(1);

 }

4. Отобразите имя узла и любые псевдонимы, которые у него могут быть:

 printf("results for host %s:\n", host);

Поделиться с друзьями: