■ Сообщение 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].
31.7. Резюме
Иногда сокеты реализуются с использованием потоков STREAMS. Для обеспечения доступа к потоковой подсистеме вводятся четыре новые функции: getmsg
, putmsg
, getpmsg
и putpmsg
. Также в потоковой подсистеме широко используется уже описанная ранее функция ioctl
.
TPI представляет собой потоковый интерфейс системы SVR4, предоставляющий доступ из верхних уровней на транспортный уровень. Он используется как сокетами, так и XTI, как показано на рис. 31.3. В этой главе в качестве примера использования основанного на сообщениях интерфейса мы разработали версию клиента времени и даты, в котором непосредственно применяется интерфейс TPI.
Упражнения
1. В листинге 31.6 мы вызываем функцию putmsg
, чтобы отправить вниз по потоку запрос на нормальное завершение соединения, а затем немедленно вызываем функцию close
для закрытия потока. Что произойдет, если наш запрос будет потерян потоковой подсистемой, а мы закроем поток?
Приложения
Приложение А
Протоколы IPv4, IPv6, ICMPv4 и ICMFV6
А.1. Введение
В этом приложении приведен обзор протоколов IPv4, IPv6, ICMPv4 и ICMPv6. Данный материал позволяет глубже понять рассмотренные в главе 2 протоколы TCP и UDP. Некоторые возможности IP и ICMP рассматриваются также более подробно и в других главах, например параметры IP (см. главу 27), и программы ping
и traceroute
(см. главу 28).
А.2. Заголовок IPv4
Вильям Л Саймон , Вильям Саймон , Наталья Владимировна Макеева , Нора Робертс , Юрий Викторович Щербатых
Зарубежная компьютерная, околокомпьютерная литература / ОС и Сети, интернет / Короткие любовные романы / Психология / Прочая справочная литература / Образование и наука / Книги по IT / Словари и Энциклопедии