Вход/Регистрация
UNIX: разработка сетевых приложений
вернуться

Стивенс Уильям Ричард

Шрифт:

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.

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

//streams/tpi_close.c

1 #include "tpi_daytime.h"

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

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

11 Close(fd);

12 }

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

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

struct T_ordrel_req {

long PRIM_type; /* T_ORDREL_REQ */

};

и посылаем ее как сообщение

M_PROTO
с помощью функции
putmsg
. Это соответствует функции XTI
t_sndrel
.

Этот пример позволил нам почувствовать специфику TPI. Приложение посылает сообщения вниз по потоку (запросы), а поставщик посылает сообщения вверх по потоку (ответы). Некоторые обмены сообщений организованы согласно простому сценарию «запрос-ответ» (связывание локального адреса), в то время как остальные могут занять некоторое время (установление соединения), позволяя нам заняться чем-то другим в процессе ожидания ответа. Для знакомства с TPI мы выбрали этот пример (написание клиента TCP) из-за его относительной простоты. Если бы мы решили написать с использованием TPI TCP-сервер, обрабатывающий одновременно несколько соединений, это было бы гораздо сложнее.

ПРИМЕЧАНИЕ

Можно сравнить количество системных вызовов, необходимых для осуществления определенных сетевых операций, показанных в этой главе, в случае применения TPI и когда используется ядро, реализующее сокеты. Связывание с локальным адресом в случае TPI требует двух системных вызовов, но в случае сокетного ядра требуется только один вызов [128, с. 454]. Для установления соединения на блокируемом дескрипторе с использованием TPI требуется три системных вызова, а в случае сокетного ядра — только один [128, с. 466].

  • Читать дальше
  • 1
  • ...
  • 458
  • 459
  • 460
  • 461
  • 462
  • 463
  • 464
  • 465
  • 466
  • 467
  • 468
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

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