-->

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

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

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

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

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

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

Перейти на страницу:
Заполнение структуры адреса сервера, установление соединения

17-22
 Мы заполняем другую структуру адреса сокета Интернета, внося в нее IP-адрес сервера (из командной строки) и порт (13). Мы вызываем нашу функцию
tpi_connect
для установления соединения.

Считывание данных с сервера, копирование в стандартный поток вывода

23-33
 Как и в случае других клиентов времени и даты, мы просто копируем данные, пришедшие по соединению, в стандартный поток вывода, останавливаясь при получении признака конца файла, присланного сервером (например, сегмент FIN). Мы сделали этот цикл похожим на тот, который использовался в коде сокетного клиента (см. листинг 1.1), поскольку наша функция
tpi_read
при нормальном завершении соединения на стороне сервера будет возвращать нулевое значение. Затем мы вызываем нашу функцию
tpi_close
для того, чтобы закрыть эту точку доступа.

Наша функция

tpi_bind
показана в листинге 31.3.

Листинг 31.3. Функция tpi_bind: связывание локального адреса с точкой доступа

//streams/tpi_bind.c

 1 #include "tpi_daytime.h"

 2 void

 3 tpi_bind(int fd, const void *addr, size_t addrlen)

 4 {

 5  struct {

 6   struct T_bind_req msg_hdr;

 7   char addr[128];

 8  } bind_req;

 9  struct {

10   struct T_bind_ack msg_hdr;

11   char addr[128];

12  } bind_ack;

13  struct strbuf ctlbuf;

14  struct T_error_ack *error_ack;

15  int flags;

16  bind_req.msg_hdr.PRIM_type = T_BIND_REQ;

17  bind_req.msg_hdr.ADDR_length = addrlen;

18  bind_req.msg_hdr.ADDR_offset = sizeof(struct T_bind_req);

19  bind_req.msg_hdr.CONIND_number = 0;

20  memcpy(bind_req.addr, addr, addrlen); /* sockaddr_in{} */

21  ctlbuf.len = sizeof(struct T_bind_req) + addrlen;

22  ctlbuf.buf = (char*)&bind_req;

23  Putmsg(fd, &ctlbuf, NULL, 0);

24  ctlbuf.maxlen = sizeof(bind_ack);

25  ctlbuf.len = 0;

26  ctlbuf.buf = (char*)&bind_ack;

27  flags = RS_HIPRI;

28  Getmsg(fd, &ctlbuf, NULL, &flags);

29  if (ctlbuf.len < (int)sizeof(long))

30   err_quit("bad length from getmsg");

31  switch (bind_ack.msg_hdr.PRIM_type) {

32  case T_BIND_ACK:

33   return;

34  case T_ERROR_ACK:

35   if (ctlbuf.len < (int)sizeof(struct T_error_ack))

36    err_quit("bad length for T_ERROR_ACK");

37   error_ack = (struct T_error_ack*)&bind_ack.msg_hdr;

38   err_quit("T_ERROR_ACK from bind (%d, %d)",

39    error_ack->TLI_error, error_ack->UNIX_error);

40  default:

41   err_quit("unexpected message type: %d", bind_ack.msg_hdr.PRlM_type);

42  }

43 }

Заполнение структуры T_bind_req

16-20
 Заголовочный файл
<sys/tihdr.h>
определяет структуру
T_bind_req
:

struct T_bind_req {

 long          PRIM_type;     /* T_BIND_REQ */

 long          ADDR_length;   /* длина адреса */

 long          ADDR_offset;   /* смещение адреса */

 unsigned long CONIND_number; /* сообщения о соединении */

 /* далее следует адрес протокола для связывания */

};

Все запросы TPI определяются как структуры, начинающиеся с поля типа

long
. Мы определяем свою собственную структуру
bind_req
, начинающуюся со структуры
T_bind_req
, после которой располагается буфер, содержащий локальный адрес для связывания. TPI ничего не говорит о содержимом буфера — оно определяется поставщиком. Поставщик TCP предполагает, что этот буфер содержит структуру
sockaddr_in
.

Мы заполняем структуру

T_bind_req
, устанавливая элемент
ADDR
_length равным размеру адреса (16 байт для структуры адреса сокета Интернета), а элемент
ADDR_offset
— равным байтовому сдвигу адреса (он следует непосредственно за структурой
T_bind_req
). У нас нет гарантии, что это местоположение соответствующим образом выровнено для записи структуры
sockaddr_in
, поэтому мы вызываем функцию
memcpy
, чтобы скопировать структуру вызывающего процесса в нашу структуру
bind_req
. Мы присваиваем элементу
CONIND_number
нулевое значение, потому что мы находимся на стороне клиента, а не на стороне сервера.

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

21-23
TPI требует, чтобы только что созданная нами структура была передана поставщику как одно сообщение
M_PROTO
. Следовательно, мы вызываем функцию
putmsg
, задавая структуру
bind_req
в качестве управляющей информации, без каких-либо данных и с флагом 0.

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