-->

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

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

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

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

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

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

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

10  hints.ai_socktype = socktype; /* 0, SOCK_STREAM, SOCK_DGRAM, ... */

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

12   return (NULL);

13  return (res); /* возвращает указатель на первый элемент в связном

                     списке */

14 }

7-13
 Функция инициализирует структуру рекомендаций (
hints
), вызывает функцию
getaddrinfo
и возвращает пустой указатель, если происходит ошибка.

Мы вызываем эту функцию в листинге 16.11, когда нам нужно использовать

getaddrinfo
для получения информации об узле и о службе и при этом мы хотим установить соединение самостоятельно.

11.12. Функция tcp_connect

Теперь мы напишем две функции, использующие функцию

getaddrinfo
для обработки большинства сценариев клиентов и серверов TCP, которые мы создаем. Первая из этих функций,
tcp_connect
, выполняет обычные шаги клиента: создание сокета TCP и соединение с сервером.

#include "unp.h"

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

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

В листинге 11.4 показан исходный код.

Листинг 11.4. Функция tcp_connect: выполнение обычных шагов клиента

/

/lib/tcp_connect.c

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

 2 int

 3 tcp_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_STREAM;

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

11   err_quit(&quot;tcp_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;tcp_connect error for %s, %s&quot;, host, serv);

24  freeaddrinfo(ressave);

25  return (sockfd);

26 }

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

7-13
 функция
getaddrinfo
вызывается один раз, когда мы задаем семейство адресов
AF_UNSPEC
и тип сокета
SOCK_STREAM
.

Перебор всех структур addrinfo до успешного выполнения или до окончания списка

14-25
 Затем пробуется каждый IP-адрес: вызываются функции
socket
и
connect
. Если выполнение функции
socket
неудачно, это не фатальная ошибка, так как такое может случиться, если был возвращен адрес IPv6, а ядро узла не поддерживает IPv6. Если выполнение функции
connect
успешно, выполняется функция
break
для выхода из цикла. В противном случае, после того как перепробованы все адреса, цикл также завершается. Функция
freeaddrinfo
освобождает всю динамически выделенную память.

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

getaddrinfo
в следующих разделах) завершается, если либо оказывается неудачным вызов функции
getaddrinfo
, либо вызов функции
connect
не выполняется успешно. Возвращение из нашей функции возможно лишь в случае успешного выполнения. Было бы сложно возвратить код ошибки (одну из констант
EAI_<i>xxx</i>
), не добавляя еще одного аргумента. Это значит, что наша функция-обертка тривиальна:

Tcp_connect(const char *host, const char *serv) {

 return(tcp_connect(host, serv));

}

Тем не менее мы по-прежнему вызываем функцию-обертку вместо функции

tcp_connect
ради сохранения единообразия в оставшейся части книги.

ПРИМЕЧАНИЕ

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

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

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

tcp_connect
.

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

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