-->

UNIX: разработка сетевых приложений

На нашем литературном портале можно бесплатно читать книгу UNIX: разработка сетевых приложений, Стивенс Уильям Ричард-- . Жанр: ОС и Сети. Онлайн библиотека дает возможность прочитать весь текст и даже без регистрации и СМС подтверждения на нашем литературном портале bazaknig.info.
UNIX: разработка сетевых приложений
Название: UNIX: разработка сетевых приложений
Дата добавления: 16 январь 2020
Количество просмотров: 390
Читать онлайн

UNIX: разработка сетевых приложений читать книгу онлайн

UNIX: разработка сетевых приложений - читать бесплатно онлайн , автор Стивенс Уильям Ричард

Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.

Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала

Перейти на страницу:

15  ressave = res;

16  do {

17   listenfd =

18    socket(res->ai_family, res->ai_socktype, res->ai_protocol);

19   if (listenfd < 0)

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

21   Setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));

22   if (bind(listenfd, res->ai_addr, res->ai_addrlen) == 0)

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

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

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

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

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

                        вызове функции socket() или bind() */

27   err_sys("tcp_listen error for %s, %s", host, serv);

28  Listen(listenfd, LISTENQ);

29  if (addrlenp)

30   *addrlenp = res->ai_addrlen; /* возвращает размер адреса протокола */

31  freeaddrinfo(ressave);

32  return (listenfd);

33 }

Вызов функции getaddrinfo

8-15
 Мы инициализируем структуру
addrinfo
с учетом следующих рекомендаций (элементов структуры
hints
):
AI_PASSIVE
, поскольку это функция для сервера,
AF_UNSPEC
для семейства адресов и
SOCK_STREAM
. Вспомните табл. 11.3: если имя узла не задано (что вполне нормально для сервера, который хочет связать с дескриптором универсальный адрес), то наличие значений
AI_PASSIVE
и
AF_UNSPEC
вызовет возвращение двух структур адреса сокета: первой для IPv6 и второй для IPv4 (в предположении, что это узел с двойным стеком).

Создание сокета и связывание с адресом

16-24
 Вызываются функции
socket
и
bind
. Если любой из вызовов окажется неудачным, мы просто игнорируем данную структуру
addrinfo
и переходим к следующей. Как было сказано в разделе 7.5, для сервера TCP мы всегда устанавливаем параметр сокета
SO_REUSEADDR
.

Проверка на наличие ошибки

25-26
 Если все вызовы функций
socket
и
bind
окажутся неудачными, мы сообщаем об ошибке и завершаем выполнение. Как и в случае с нашей функцией
tcp_connect
из предыдущего раздела, мы не пытаемся возвратить ошибку из этой функции.

27
 Сокет превращается в прослушиваемый сокет с помощью функции
listen
.

Возвращение размера структуры адреса

28-31
 Если аргумент
addrlenp
является непустым указателем, мы возвращаем размер адресов протокола через этот указатель. Это позволяет вызывающему процессу выделять память для структуры адреса сокета, чтобы получить адрес протокола клиента из функции accept (см. также упражнение 11.7).

Пример: сервер времени и даты

В листинге 11.7 показан наш сервер времени и даты из листинга 4.2, переписанный с использованием функции

tcp_listen
.

Листинг 11.7. Сервер времени и даты, переписанный с использованием функции tcp_listen

//names/daytimetcpsrv1.c

 1 #include "unp.h"

 2 #include <time.h>

 3 int

 4 main(int argc, char **argv)

 5 {

 6  int listenfd, connfd;

 7  socklen_t addrlen, len;

 8  char = buff[MAXLINE];

 9  time_t ticks;

10  struct sockaddr_storage cliaddr;

11  if (argc != 2)

12   err_quit("usage: daytimetcpsrv1 <service or port#>");

13  listenfd = Tcp_listen(NULL, argv[1], &addrlen);

14  for (;;) {

15   len = sizeof(cliaddr);

16   connfd = Accept(listenfd, (SA*)&cliaddr, &len);

17   printf("connection from %sn", Sock_ntop((SA*)&cliaddr, len));

18   ticks = time(NULL);

19   snprintf(buff, sizeof(buff), "%.24srn", ctime(&ticks));

20   Write(connfd, buff, strlen(buff));

21   Close(connfd);

22  }

23 }

Ввод имени службы или номера порта в качестве аргумента командной строки

11-12
 Нам нужно использовать аргумент командной строки, чтобы задать либо имя службы, либо номер порта. Это упрощает проверку нашего сервера, поскольку связывание с портом 13 для сервера времени и даты требует прав привилегированного пользователя.

Создание прослушиваемого сокета

13
 Функция
tcp_listen
создает прослушиваемый сокет. В качестве третьего аргумента мы передаем нулевой указатель, потому что нам безразличен размер структуры адреса, используемого данным семейством: мы будем работать со структурой
sockaddr_storage
.

Перейти на страницу:
Комментариев (0)
название