11.16. Функция udp_server

We use cookies. Read the Privacy and Cookie Policy

11.16. Функция udp_server

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

#include "unp.h"

int udp_server(const char *hostname, const char *service, socklen_t *lenptr);

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

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

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

//lib/udp_server.c

 1 #include "unp.h"

 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(&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, &hints, &res)) != 0)

12   err_quit("udp_server error for %s, %s: %s",

13    host, serv, gai_strerror(n));

14  ressave = res;

15  do {

16   sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);

17   if (sockfd < 0)

18    continue; /* ошибка, пробуем следующий адрес */

19   if (bind(sockfd, res->ai_addr, res->ai_addrlen) == 0)

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

21   Close(sockfd); /* ошибка при вызове функции bind, закрываем

                       сокет и пробуем следующий адрес */

22  } while ((res = res->ai_next) != NULL);

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

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

24   err_sys("udp_server error for %s, %s", host, serv);

25  if (addrlenp)

26   *addrlenp = res->ai_addrlen; /* возвращается размер адреса

                                     протокола */

27  freeaddrinfo(ressave);

28  return (sockfd);

29 }

Эта функция практически идентична функции tcp_listen, в ней нет только вызова функции listen. Мы устанавливаем семейство адресов AF_UNSPEC, но вызывающий процесс может использовать ту же технологию, которую мы описали при рассмотрении листинга 11.6, чтобы потребовать использование определенного протокола (IPv4 или IPv6).

Мы не устанавливаем параметр сокета SO_REUSEADDR для сокета UDP, поскольку этот параметр сокета может допустить связывание множества сокетов с одним и тем же портом UDP на узлах, поддерживающих многоадресную передачу, как мы говорили в разделе 7.5. Поскольку у сокета UDP нет аналога состояния TIME_WAIT, свойственного сокетам TCP, нет необходимости устанавливать этот параметр при запуске сервера.

Данный текст является ознакомительным фрагментом.