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

 long OPT_length; /* длина параметра */

 long OPT_offset; /* смещение параметра */

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

};

Мы снова вызываем функцию getmsg, но ожидаемое нами сообщение посылается как сообщение типа M_PROTO, а не как сообщение M_PCPROTO, поэтому мы обнуляем флаги. Если мы получаем сообщение T_CONN_CON, значит, соединение установлено, и мы возвращаемся, но если соединение не было установлено (по причине того, что процесс собеседника не запущен, истекло время ожидания или еще по какой-либо причине), то вместо этого вверх по потоку отправляется сообщение T_DISCON_IND:

struct T_discon_ind {

 long PRIM_type;     /* T_DISCON_IND */

 long DISCON_reason; /* причина разрыва соединения */

 long SEQ_number;    /* порядковый номер */

};

Мы можем посмотреть, какие ошибки могут быть возвращены поставщиком. Сначала мы задаем IP-адрес узла, на котором не запущен сервер времени и даты:

solaris26 % tpi_daytime 192.168.1.10

tpi_connect2: T_DISCON_IND from conn (146)

Код 146 соответствует ошибке ECONNREFUSED. Затем мы задаем IP-адрес, который не связан с Интернетом:

solaris26 % tpi_daytime 192.3.4.5

tpi_connect2: T_DISCON_IND from conn (145)

На этот раз возвращается ошибка ETIMEDOUT. Но если мы снова запустим нашу программу, задавая тот же самый IP-адрес, то получим другую ошибку:

solaris26 % tpi_daytime 192.3.4.5

tpi_connect2: T_DISCON_IND from conn (148)

На этот раз мы получаем ошибку EHOSTUNREACH. Различие в том, что в первый раз не было возвращено сообщение ICMP о недоступности узла, а во второй раз мы получили это сообщение.

Следующая функция, которую мы рассмотрим, — это tpi_read, показанная в листинге 31.5. Она считывает данные из потока.

Листинг 31.5. Функция tpi_read: считывание данных из потока

//streams/tpi_read.c

 1 #include "tpi_daytime.h"

 2 ssize_t

 3 tpi_read(int fd, void *buf, size_t len)

 4 {

 5  struct strbuf ctlbuf;

 6  struct strbuf datbuf;

 7  union T_primitives rcvbuf;

 8  int flags;

 9  ctlbuf maxlen = sizeof(union T_primitives);

10  ctlbuf.buf = (char*)&rcvbuf

11  datbuf.maxlen = len;

12  datbuf.buf = buf;

13  datbuf.len = 0;

14  flags = 0;

15  Getmsg(fd, &ctlbuf, &datbuf, &flags);

16  if (ctlbuf.len >= (int)sizeof(long)) {

17   if (rcvbuf.type == T_DATA_IND)

18    return (datbuf.len);

19   else if (rcvbuf.type == T_ORDREL_IND)

20    return (0);

21   else

22    err_quit("tpi_read: unexpected type %d", rcvbuf.type);

23  } else if (ctlbuf.len == -1)

24   return (datbuf.len);

25  else

26   err_quit("tpi_read: bad length from getmsg");

27 }

Считывание управляющей информации и данных, обработка ответа

9-26 На этот раз мы вызываем функцию getmsg для считывания как данных, так и управляющей информации. Структура strbuf, предназначенная для данных, указывает на буфер вызывающего процесса. В потоке события могут развиваться по четырем различным сценариям.

■ Данные могут прибыть в виде сообщения M_DATA, и указанием на это является возвращенное значение длины управляющей информации, равное -1. Данные скопированы в буфер вызывающего процесса функцией getmsg, и функция просто возвращает длину этих данных.

■ Данные могут прибыть как сообщение T_DATA_IND, в этом случае управляющая информация будет содержаться в структуре T_data_ind:

struct T_data_ind {

 long PRIM_type; /* T_DATA_IND */

 long MORE_flag; /* еще данные */

};

Если возвращено такое сообщение, мы игнорируем поле MORE_flag (оно вообще не задается для таких протоколов, как TCP) и просто возвращаем длину данных, скопированных в буфер вызывающего процесса функцией getmsg.

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

Все книги серии Мастер-класс

Секреты резьбы по дереву
Секреты резьбы по дереву

Изделия из древесины и материалов, имитирующих ее текстуру, привычным образом окружают нас в повседневной жизни, поэтому мы относимся к ней как к чему-то обыденному. Но как только ее коснется умелая рука мастера резьбы по дереву, рождается произведение искусства и раскрываются такие качества древесины, как богатая фактура, разнообразие цветов, особая теплота. Эта книга поможет читателю открыть для себя удивительный мир творчества и познать секреты резьбы по дереву. Автор надеется, что начинающие резчики найдут в ней интересный и полезный материал, который позволит им стать мастерами. В приложении представлены рисунки орнаментов и различных узоров, которые на первых порах можно копировать, а по мере приобретения навыка на их основе разрабатывать свои образцы.

Галина Алексеевна Серикова

Сделай сам / Хобби и ремесла / Руководства / Дом и досуг / Словари и Энциклопедии

Похожие книги