-->

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

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

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

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

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

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

Перейти на страницу:
Вызов функции getmsg для чтения сообщений с высоким приоритетом

24-30
Ответом на наш запрос
T_BIND_REQ
будет либо сообщение
T_BIND_ACK
, либо сообщение
T_ERROR_ACK
. Сообщения, содержащие подтверждение, отправляются как сообщения с высоким приоритетом (
M_PCPROTO
), так что мы считываем их при помощи функции
getmsg
с флагом
RS_HIPRI
. Поскольку ответ является сообщением с высоким приоритетом, он получает преимущество перед всеми обычными сообщениями в потоке.

Эти два сообщения выглядят следующим образом:

struct T_bind_ack {

 long          PRIM_type;     /* T_BIND_ACK */

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

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

 unsigned long CONIND_number; /* индекс подключения для помещения

                                 в очередь */

};

 /* затем следует связанный адрес */

struct T_error_ack {

 long PRIM_type;  /* T_ERROR_ACK */

 long ERROR_prim; /* примитивная ошибка ввода */

 long TLI_error;  /* код ошибки TLI */

 long UNIX_error; /* код ошибки UNIX */

};

В начале каждого сообщения указан его тип, так что мы можем начать считывать ответ, предполагая, что это сообщение

T_BIND_ACK
, а затем, прочитав его тип, обрабатывать его тем или иным способом. Мы не ждем никаких данных от поставщика, поэтому третий аргумент функции
getmsg
мы задаем как пустой указатель.

ПРИМЕЧАНИЕ

Когда мы проверяем, соответствует ли количество возвращенной управляющей информации по меньшей мере размеру длинного целого, нужно проявить осторожность, преобразуя значение sizeof в целое число. Оператор sizeof возвращает целое число без знака, но существует вероятность того, что значение возвращенного поля len будет -1. Поскольку при выполнении операции сравнения слева располагается значение со знаком, а справа — без знака, компилятор преобразует значение со знаком в значение без знака. Если рассматривать -1 как целое без знака в архитектуре с дополнением до 2, это число получается очень большим, то есть -1 оказывается больше 4 (если предположить, что длинное целое число занимает 4 байта).

Обработка ответа

31-33
 Если ответ — это сообщение
T_BIND_ACK
, то связывание прошло успешно, и мы возвращаемся. Фактический адрес, связанный с точкой доступа, возвращается в элементе
addr
нашей структуры
bind_ack
, которую мы игнорируем.

34-39
 Если ответ — это сообщение
T_ERROR_ACK
, мы проверяем, было ли сообщение получено целиком, и выводим три значения, содержащиеся в возвращенной структуре. В этой простой программе при возникновении ошибки мы просто прекращаем выполнение и ничего не возвращаем вызывающему процессу.

Чтобы увидеть ошибки, которые могут возникнуть в результате запроса на связывание, мы слегка изменим нашу функцию

main
и попробуем связать какой- либо порт, отличный от 0. Например, если мы попробуем связать порт 1 (что требует прав привилегированного пользователя, так как это порт с номером меньше 1024), мы получим следующий результат:

solaris % <b>tpi_daytime 127.0.0.1</b>

T_ERROR_ACK from bind (3, 0)

В этой системе значение константы

EACCESS
равно 3. Если мы поменяем номер порта, задав значение большее 1023, но используемое в настоящий момент другой точкой доступа TCP, мы получим:

solaris % <b>tpi_daytime 127.0.0.1</b>

T_ERROR_ACK from bind (23, 0)

В данной системе значение константы

EADDRBUSY
равно 23.

Следующая функция показана в листинге 31.4. Это функция

tpi_connect
, устанавливающая соединение с сервером.

Листинг 31.4. Функция tpi_connect: установление соединения с сервером

//streams/tpi_connect.c

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

 2 void

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

 4 {

 5  struct {

 6   struct T_conn_req msg_hdr;

 7   char addr[128];

 8  } conn_req;

 9  struct {

10   struct l_conn_con msg_hdr;

11   char addr[128];

12  } conn_con;

13  struct strbuf ctlbuf;

14  union T_primitives rcvbuf;

15  struct T_error_ack *error_ack;

16  struct T_discon_ind *discon_ind;

17  int flags;

18  conn_req.msg_hdr.PRIM_type = T_CONN_REQ;

19  conn_req.msg_hdr.DEST_length = addrlen;

20  conn_req.msg_hdr.DEST_offset = sizeof(struct T_conn_req);

21  conn_req.msg_hdr.OPT_length = 0;

22  conn_req.msg_hdr.OPT_offset = 0;

23  memcpy(conn_req.addr, addr, addrlen); /* sockaddr_in{} */

24  ctlbuf.len = sizeof(struct T_conn_req) + addrlen;

25  ctlbuf.buf = (char*)&amp;conn_req;

26  Putmsg(fd, &amp;ctlbuf, NULL, 0);

27  ctlbuf.maxlen = sizeof(union T_primitives);

28  ctlbuf.len = 0;

29  ctlbuf.buf = (char*)&amp;rcvbuf;

30  flags = RS_HIPRI;

31  Getmsg(fd, &amp;ctlbuf, NULL, &amp;flags);

32  if (ctlbuf.len &lt; (int)sizeof(long))

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