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

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

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

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

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

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

1 ... 39 40 41 42 43 44 45 46 47 ... 399 ВПЕРЕД
Перейти на страницу:

4.6. Функция accept

Функция

accept
вызывается сервером TCP для возвращения следующего установленного соединения из начала очереди полностью установленных соединений (см. рис. 4.2). Если очередь полностью установленных соединений пуста, процесс переходит в состояние ожидания (по умолчанию предполагается блокируемый сокет).

#include <sys/socket.h>

int accept(int <i>sockfd</i>, struct sockaddr *<i>cliaddr</i>, socklen_t *<i>addrlen</i>);

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

Аргументы

cliaddr
и
addrlen
используются для возвращения адреса протокола подключившегося процесса (клиента). Аргумент
addrlen
— это аргумент типа «значение-результат» (см. раздел 3.3). Перед вызовом мы присваиваем целому числу, на которое указывает
*addrlen
, размер структуры адреса сокета, на которую указывает аргумент
cliaddr
, и по завершении функции это целое число содержит действительное число байтов, помещенных ядром в структуру адреса сокета.

Если выполнение функции

accept
прошло успешно, она возвращает новый дескриптор, автоматически созданный ядром. Этот дескриптор используется для обращения к соединению TCP с конкретным клиентом. При описании функции
accept
мы называем ее первый аргумент прослушиваемым сокетом (listening socket) (дескриптор, созданный функцией
socket
и затем используемый в качестве аргумента для функций
bind
и
listen
), а значение, возвращаемое этой функцией, мы называем присоединенным сокетом (connected socket). Сервер обычно создает только один прослушиваемый сокет, который существует в течение всего времени жизни сервера. Затем ядро создает по одному присоединенному сокету для каждого клиентского соединения, принятого с помощью функции
accept
(для которого завершено трехэтапное рукопожатие TCP). Когда сервер заканчивает предоставление сервиса данному клиенту, сокет закрывается.

Эта функция возвращает до трех значений: целое число, которое является либо дескриптором сокета, либо кодом ошибки, а также адрес протокола клиентского процесса (через указатель

cliaddr
) и размер адреса (через указатель
addrlen
). Если нам не нужно, чтобы был возвращен адрес протокола клиента, следует сделать указатели
cliaddr
и
addrlen
пустыми указателями.

В листинге 1.5 показаны эти моменты. Присоединенный сокет закрывается при каждом прохождении цикла, но прослушиваемый сокет остается открытым в течение времени жизни сервера. Мы также видим, что второй и третий аргументы функции

accept
являются пустыми указателями, поскольку нам не нужно идентифицировать клиент.

Пример: аргументы типа «значение-результат»

В листинге 4.2 представлен измененный код из листинга 1.5 (вывод IP-адреса и номера порта клиента), обрабатывающий аргумент типа «значение-результат» функции accept.

Листинг 4.2. Сервер определения времени и даты, сообщающий IP-адрес и номер порта клиента

//intro/daytimetcpsrv1.c

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

 2 #include &lt;time.h&gt;

 3 int

 4 main(int argc, char **argv)

 5 {

 6  int listenfd, connfd;

 7  socklen_t len;

 8  struct sockaddr_in servaddr, cliaddr;

 9  char buff[MAXLINE];

10  time_t ticks;

11  listenfd = Socket(AF_INET, SOCK_STREAM, 0);

12  bzero(&amp;servaddr, sizeof(servaddr));

13  servaddr.sin_family = AF_INET;

14  servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

15  servaddr.sin_port = htons(13); /* сервер времени и даты */

16  Bind(listenfd, (SA*)&amp;servaddr, sizeof(servaddr));

17  Listen(listenfd, LISTENQ);

18  for (;;) {

19   len = sizeof(cliaddr);

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

21   printf(&quot;connection from %s, port %dn&quot;,

22    Inet_ntop(AF_INET, &amp;cliaddr.sin_addr, buff, sizeof(buff));

23   ntohs(cliaddr.sin_port));

24   ticks = time(NULL);

25   snprintf(buff, sizeof(buff), &quot;% 24srn&quot;, ctime(&amp;ticks));

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

27   Close(connfd);

28  }

29 }

Новые объявления

7-8
 Мы определяем две новых переменных:
len
, которая будет переменной типа «значение-результат», и
cliaddr
, которая будет содержать адрес протокола клиента.

Принятие соединения и вывод адреса клиента

19-23
 Мы инициализируем переменную
len
, присвоив ей значение, равное размеру структуры адреса сокета, и передаем указатель на структуру
cliaddr
и указатель на
len
в качестве второго и третьего аргументов функции
accept
. Мы вызываем функцию
inet_ntop
(см. раздел 3.7) для преобразования 32-битового IP-адреса в структуре адреса сокета в строку ASCII (точечно-десятичную запись), а затем вызываем функцию
ntohs
(см. раздел 3.4) для преобразования сетевого порядка байтов в 16-битовом номере порта в порядок байтов узла.

ПРИМЕЧАНИЕ

При вызове функции sock_ntop вместо inet_ntop наш сервер станет меньше зависеть от протокола, однако он все равно зависит от IPv4. Мы покажем версию этого сервера, не зависящего от протокола, в листинге 11.7.

1 ... 39 40 41 42 43 44 45 46 47 ... 399 ВПЕРЕД
Перейти на страницу:
Комментариев (0)
название