Литмир - Электронная Библиотека
Содержание  
A
A
ПРИМЕЧАНИЕ

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

Мы запускаем наш клиент, задавая имя узла с записью типа AAAA и типа А. Поскольку функция

getaddrinfo
в первую очередь возвращает структуру с записью типа AAAA, создается сокет IPv6:

freebsd % <b>daytimeudpcli1 aix daytime</b>

sending to 3ffe:b80:1f8d:2:204:acff:fe17:bf38

Sun Jul 23:21:12 2003

Затем мы задаем адрес того же узла в точечно-десятичной записи, в результате чего создается сокет IPv4:

freebsd % <b>daytimeudpcli1 192.168.42.2 daytime</b>

sending to 192.168.42.2

Sun Jul 23:21:40 2003

11.15. Функция udp_connect

Наша функция

udp_connect
создает присоединенный сокет UDP.

#include &quot;unp.h&quot;

int udp_connect(const char *<i>hostname</i>, const char *<i>service</i>);

<i>Возвращает; дескриптор присоединенного сокета в случае успешного выполнения, в случае ошибки ничего не возвращает</i>

В случае присоединенного сокета UDP два последних аргумента, которые требовались в функции

udp_client
, больше не нужны. Вызывающий процесс может вызвать функцию
write
вместо
sendto
, таким образом нашей функции не нужно возвращать структуру адреса сокета и ее длину. В листинге 11.11 представлен исходный код.

Листинг 11.11. Функция udp_connect: создание присоединенного сокета UDP

//lib/udp_connect.c

 1 #include &quot;unp.h&quot;

 2 int

 3 udp_connect(const char *host, const char *serv)

 4 {

 5  int sockfd, n;

 6  struct addrinfo hints, *res, *ressave;

 7  bzero(&amp;hints, sizeof(struct addrinfo));

 8  hints.ai_family = AF_UNSPEC;

 9  hints.ai_socktype = SOCK_DGRAM;

10  if ((n = getaddrinfo(host, serv, &amp;hints, &amp;res)) != 0)

11   err_quit(&quot;udp_connect error for %s, %s: %s&quot;,

12    host, serv, gai_strerror(n));

13  ressave = res;

14  do {

15   sockfd = socket(res-&gt;ai_family, res-&gt;ai_socktype, res-&gt;ai_protocol);

16   if (sockfd &lt; 0)

17    continue; /* игнорируем этот адрес */

18   if (connect(sockfd, res-&gt;ai_addr, res-&gt;ai_addrlen) == 0)

19    break; /* успех */

20   Close(sockfd); /* игнорируем этот адрес */

21  } while ((res = res-&gt;ai_next) != NULL);

22  if (res == NULL) /* значение errno устанавливается при

                        последнем вызове функции connect() */

23  err_sys(&quot;udp_connect error for %s, %s&quot;, host, serv);

24  freeaddrinfo(ressave);

25  return (sockfd);

26 }

Эта функция почти идентична функции

tcp_connect
. Однако отличие в том, что при вызове функции
connect
для сокета UDP ничего не отправляется собеседнику. Если что-то не в порядке (собеседник недоступен или на заданном порте не запущен сервер), вызывающий процесс не обнаружит этого, пока не пошлет собеседнику дейтаграмму.

11.16. Функция udp_server

Наша последняя функция, предоставляющая более простой интерфейс для функции

getaddrinfo
, — это функция
udp_server
.

#include &quot;unp.h&quot;

int udp_server(const char *<i>hostname</i>, const char *<i>service</i>, socklen_t *<i>lenptr</i>);

<i>Возвращает; дескриптор неприсоединенного сокета в случае успешного выполнения, в случае ошибки не возвращает ничего</i>

Аргументы функции те же, что и для функции

tcp_listen
: необязательный
hostname
, обязательный
service
(для связывания номер порта) и необязательный указатель на переменную, в которой возвращается размер структуры адреса сокета. В листинге 11.12 представлен исходный код.

Листинг 11.12. Функция udp_server: создание неприсоединенного сокета для сервера UDP

//lib/udp_server.c

 1 #include &quot;unp.h&quot;

 2 int

 3 udp_server(const char *host, const char *serv, socklen_t *addrlenp)

 4 {

 5  int sockfd, n;

 6  struct addrinfo hints, *res, *ressave;

 7  bzero(&amp;hints, sizeof(struct addrinfo));

 8  hints.ai_flags = AI_PASSIVE;

 9  hints.ai_family = AF_UNSPEC;

10  hints.ai_socktype = SOCK_DGRAM;

11  if ((n = getaddrinfo(host, serv, &amp;hints, &amp;res)) != 0)

12   err_quit(&quot;udp_server error for %s, %s: %s&quot;,

13    host, serv, gai_strerror(n));

136
{"b":"225366","o":1}