Чтение онлайн

на главную

Жанры

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

Мы снова вызываем функцию

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
.

Сообщение

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

struct T_ordrel_ind {

long PRIM_type; /* T_ORDREL_IND */

};

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

Сообщение

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

Поделиться:
Популярные книги

Последний Паладин. Том 3

Саваровский Роман
3. Путь Паладина
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Последний Паладин. Том 3

Последний попаданец 5

Зубов Константин
5. Последний попаданец
Фантастика:
юмористическая фантастика
рпг
5.00
рейтинг книги
Последний попаданец 5

Убивать чтобы жить 6

Бор Жорж
6. УЧЖ
Фантастика:
боевая фантастика
космическая фантастика
рпг
5.00
рейтинг книги
Убивать чтобы жить 6

6 Секретов мисс Недотроги

Суббота Светлана
2. Мисс Недотрога
Любовные романы:
любовно-фантастические романы
эро литература
7.34
рейтинг книги
6 Секретов мисс Недотроги

Измена

Рей Полина
Любовные романы:
современные любовные романы
5.38
рейтинг книги
Измена

Курсант: Назад в СССР 13

Дамиров Рафаэль
13. Курсант
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Курсант: Назад в СССР 13

Газлайтер. Том 6

Володин Григорий
6. История Телепата
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Газлайтер. Том 6

Купидон с топором

Юнина Наталья
Любовные романы:
современные любовные романы
7.67
рейтинг книги
Купидон с топором

Виконт. Книга 3. Знамена Легиона

Юллем Евгений
3. Псевдоним `Испанец`
Фантастика:
фэнтези
попаданцы
аниме
7.00
рейтинг книги
Виконт. Книга 3. Знамена Легиона

Попаданка в деле, или Ваш любимый доктор - 2

Марей Соня
2. Попаданка в деле, или Ваш любимый доктор
Любовные романы:
любовно-фантастические романы
7.43
рейтинг книги
Попаданка в деле, или Ваш любимый доктор - 2

Усадьба леди Анны

Ром Полина
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Усадьба леди Анны

Титан империи 2

Артемов Александр Александрович
2. Титан Империи
Фантастика:
фэнтези
боевая фантастика
аниме
5.00
рейтинг книги
Титан империи 2

Вечный. Книга I

Рокотов Алексей
1. Вечный
Фантастика:
боевая фантастика
попаданцы
рпг
5.00
рейтинг книги
Вечный. Книга I

Убивать чтобы жить 5

Бор Жорж
5. УЧЖ
Фантастика:
боевая фантастика
космическая фантастика
рпг
5.00
рейтинг книги
Убивать чтобы жить 5