UNIX: разработка сетевых приложений
Шрифт:
26 *addrlenp = res->ai_addrlen; /* возвращается размер адреса
протокола */
27 freeaddrinfo(ressave);
28 return (sockfd);
29 }
Эта функция практически идентична функции
tcp_listen
, в ней нет только вызова функции listen
. Мы устанавливаем семейство адресов AF_UNSPEC
, но вызывающий процесс может использовать ту же технологию, которую мы описали при рассмотрении листинга 11.6, чтобы потребовать использование определенного
Мы не устанавливаем параметр сокета
SO_REUSEADDR
для сокета UDP, поскольку этот параметр сокета может допустить связывание множества сокетов с одним и тем же портом UDP на узлах, поддерживающих многоадресную передачу, как мы говорили в разделе 7.5. Поскольку у сокета UDP нет аналога состояния TIME_WAIT, свойственного сокетам TCP, нет необходимости устанавливать этот параметр при запуске сервера. Пример: не зависящий от протокола UDP-сервер времени и даты
В листинге 11.13 представлен наш сервер времени и даты, полученный путем модификации листинга 11.8 и предназначенный для использования UDP.
Листинг 11.13. Не зависящий от протокола UDP-сервер времени и даты
//names/daytimeudpsrv2.c
1 #include "unp.h"
2 #include <time.h>
3 int
4 main(int argc, char **argv)
5 {
6 int sockfd;
7 ssize_t n;
8 char buff[MAXLINE];
9 time_t ticks;
10 socklen_t addrlen, len;
11 struct sockaddr_storage cliaddr;
12 if (argc == 2)
13 sockfd = Udp_server(NULL, argv[1], &addrlen);
14 else if (argc == 3)
15 sockfd = Udp_server(argv[1], argv[2], &addrlen);
16 else
17 err_quit("usage: daytimeudpsrv [ <host> ] <service or port>");
18 for (;;) {
19 len = sizeof(cliaddr);
20 n = Recvfrom(sockfd, buff, MAXLINE, 0, (SA*)&cliaddr, &len);
21 printf("datagram from %s\n", Sock_ntop((SA*)&cliaddr, len));
22 ticks = time(NULL);
23 snprintf(buff, sizeof(buff), "% 24s\r\n", ctime(&ticks));
24 Sendto(sockfd, buff, strlen(buff), 0, (SA*)&cliaddr, len);
25 }
26 }
11.17. Функция getnameinfo
Эта функция дополняет функцию
getaddrinfo
: она получает адрес сокета и возвращает одну символьную строку с описанием узла и другую символьную строку с описанием службы. Эта функция предоставляет указанную информацию в не зависящем от протокола виде, то есть вызывающему процессу неважно, какой тип адреса протокола содержится в структуре адреса сокета, поскольку эти подробности обрабатываются функцией.
#include <netdb.h>
int getnameinfo(const struct sockaddr * sockaddr, socklen_t addrlen, char * host,
size_t hostlen, char * serv, size_t servlen, int flags);
Возвращает 0
в случае успешного выполнения, -1 в случае ошибки
Аргумент
sockaddr
указывает на структуру адреса сокета, содержащую адрес протокола, преобразуемый в строку, удобную для человеческого восприятия, а аргумент addrlen
содержит длину этой структуры. Эта структура и ее длина обычно возвращаются любой из следующих функций: accept
, recvfrom
, getsockname
или getpeername
. Вызывающий процесс выделяет в памяти пространство для двух строк, удобных для человеческого восприятия: аргументы
host
и hostlen
определяют строку, описывающую узел, а аргументы serv
и servlen
определяют строку, которая описывает службы. Если вызывающему процессу не нужна возвращаемая строка с описанием узла, задается нулевая длина этой строки ( hostlen
). Аналогично, нулевое значение аргумента servlen
означает, что не нужно возвращать информацию о службе. Разница между функциями
sock_ntop
и getnameinfo
состоит в том, что первая не задействует DNS, а только возвращает IP-адрес и номер порта. Последняя же обычно пытается получить имя и для узла, и для службы. В табл. 11.4 показаны шесть флагов, которые можно задать для изменения действия, выполняемого функцией
getnameinfo
. Таблица 11.4. Флаги функции getnameinfo
Константа | Описание |
---|---|
NI_DGRAM | Дейтаграммный сокет |
NI_NAMEREQD | Возвращать ошибку, если невозможно получить имя узла по его адресу |
NI_NOFQDN | Возвращать только ту часть FQDN, которая содержит имя узла |
NI_NUMERICHOST | Возвращать численное значение адреса вместо имени узла |
NI_NUMERICSCOPE | Возвращать численное значение идентификатора области |
NI_NUMERICSERV | Возвращать номер порта вместо имени службы |
Флаг
NI_DGRAM
должен быть задан, когда вызывающий процесс знает, что работает с дейтаграммным сокетом. Причина в том, что если функции getnameinfo
задать только IP-адрес и номер порта в структуре адреса сокета, она не сможет определить протокол (TCP или UDP). Существует несколько номеров портов, которые в случае TCP задействованы для одной службы, а в случае UDP для совершенно другой. Примером может служить порт 514, используемый службой rsh
в TCP и службой syslog
в UDP.
Поделиться:
Популярные книги
Путь Шедара
4. Другая сторона
Фантастика:
боевая фантастика
6.83
рейтинг книги
Метаморфозы Катрин
Фантастика:
фэнтези
8.26
рейтинг книги
Охота на разведенку
Любовные романы:
современные любовные романы
эро литература
6.76
рейтинг книги
Я до сих пор не князь. Книга XVI
16. Дорогой барон!
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Последний Паладин
1. Путь Паладина
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
"Малыш"
2. Девочка с придурью
Любовные романы:
современные любовные романы
эро литература
6.00
рейтинг книги
Мастер Разума II
2. Мастер Разума
Фантастика:
героическая фантастика
попаданцы
аниме
5.75
рейтинг книги
Здравствуй, 1985-й
2. Девяностые
Фантастика:
альтернативная история
5.25
рейтинг книги
Счастливый торт Шарлотты
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Назад в СССР: 1984
1. Спасти ЧАЭС
Фантастика:
попаданцы
альтернативная история
4.80
рейтинг книги
Не грози Дубровскому! Том IX
9. РОС: Не грози Дубровскому!
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Секретарша генерального
Любовные романы:
современные любовные романы
эро литература
короткие любовные романы
8.46
рейтинг книги
Газлайтер. Том 2
2. История Телепата
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Искушение генерала драконов
2. Генералы драконов
Любовные романы:
любовно-фантастические романы
5.00