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.
Поделиться:
Популярные книги
Сын Тишайшего
1. Царь Федя
Фантастика:
попаданцы
альтернативная история
фэнтези
5.20
рейтинг книги
"Искажающие реальность" Компиляция. Книги 1-14
Искажающие реальность
Фантастика:
боевая фантастика
космическая фантастика
киберпанк
рпг
5.00
рейтинг книги
Школа. Первый пояс
2. Путь
Фантастика:
фэнтези
7.67
рейтинг книги
Невеста на откуп
2. Невеста на откуп
Фантастика:
фэнтези
5.83
рейтинг книги
Убивать чтобы жить 2
2. УЧЖ
Фантастика:
героическая фантастика
боевая фантастика
рпг
5.00
рейтинг книги
Вперед в прошлое!
1. Вперед в прошлое
Фантастика:
попаданцы
5.00
рейтинг книги
Аргумент барона Бронина 4
4. Аргумент барона Бронина
Фантастика:
попаданцы
аниме
сказочная фантастика
фэнтези
5.00
рейтинг книги
Измена. (Не)любимая жена олигарха
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Измена. Право на обман
2. Измены
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Бастард Императора. Том 7
7. Бастард Императора
Фантастика:
городское фэнтези
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Жаба с кошельком
19. Любительница частного сыска Даша Васильева
Детективы:
иронические детективы
8.26
рейтинг книги
Бастард Императора. Том 11
11. Бастард Императора
Фантастика:
городское фэнтези
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Академия чаросвет. Тень
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Наследие Маозари 4
4. Наследие Маозари
Фантастика:
фэнтези
попаданцы
5.00