Литмир - Электронная Библиотека
Содержание  
A
A

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

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

};

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

solaris26 % <b>tpi_daytime 192.168.1.10</b>

tpi_connect2: T_DISCON_IND from conn (146)

Код 146 соответствует ошибке

ECONNREFUSED
. Затем мы задаем IP-адрес, который не связан с Интернетом:

solaris26 % <b>tpi_daytime 192.3.4.5</b>

tpi_connect2: T_DISCON_IND from conn (145)

На этот раз возвращается ошибка

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

solaris26 % <b>tpi_daytime 192.3.4.5</b>

tpi_connect2: T_DISCON_IND from conn (148)

На этот раз мы получаем ошибку

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

Следующая функция, которую мы рассмотрим, — это

tpi_read
, показанная в листинге 31.5. Она считывает данные из потока.

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

//streams/tpi_read.c

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

 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*)&amp;rcvbuf;

11  datbuf.maxlen = len;

12  datbuf.buf = buf;

13  datbuf.len = 0;

14  flags = 0;

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

16  if (ctlbuf.len &gt;= (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(&quot;tpi_read: unexpected type %d&quot;, rcvbuf.type);

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

24   return (datbuf.len);

25  else

26   err_quit(&quot;tpi_read: bad length from getmsg&quot;);

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
.

■ Сообщение

T_ORDREL_IND
возвращается, если все данные получены и следующим элементом является сегмент
FIN
:

struct T_ordrel_ind {

 long PRIM_type; /* T_ORDREL_IND */

};

Это нормальное завершение. Мы просто возвращаем нулевое значение, указывая вызывающему процессу, что по соединению получен признак конца файла.

■ Сообщение

T_DISCON_IND
возвращается, если произошел разрыв соединения. Наша последняя функция — это
tpi_close
, показанная в листинге 31.6.

Листинг 31.6. Функция tpi_close: отправка запроса о завершении собеседнику

//streams/tpi_close.c

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

 2 void

 3 tpi_close(int fd)

 4 {

 5  struct T_ordrel_req ordrel_req;

 6  struct strbuf ctlbuf;

 7  ordrel_req PRIM_type = T_ORDREL_REQ;

 8  ctlbuf.len = sizeof(struct T_ordrel_req);

 9  ctlbuf.buf = (char*)&amp;ordrel_req;

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

11  Close(fd);

12 }

Отправка запроса о завершении собеседнику

7-10
 Мы формируем структуру
T_ordrel_req
:

struct T_ordrel_req {

 long PRIM_type; /* T_ORDREL_REQ */

365
{"b":"225366","o":1}