};
и посылаем ее как сообщение
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
Уровень IP обеспечивает не ориентированную на установление соединения (connectionless) и ненадежную службу доставки дейтаграмм (RFC 791 [94]). Уровень IP делает все возможное для доставки IP-дейтаграммы определенному адресату, но не гарантирует, что дейтаграмма будет доставлена, прибудет в нужном порядке относительно других пакетов, а также будет доставлена в единственном экземпляре. Если требуется надежная доставка дейтаграммы, она должна быть обеспечена на более высоком уровне. В случае приложений TCP и SCTP надежность обеспечивается транспортным уровнем. Приложению UDP надежность должно обеспечивать само приложение, поскольку уровень UDP также не предоставляет гарантии надежной доставки дейтаграмм, что было показано на примере в разделе 22.5.
Одной из наиболее важных функций уровня IP является маршрутизация (routing). Каждая IP-дейтаграмма содержит адрес отправителя и адрес получателя. На рис. А.1 показан формат заголовка Ipv4.
Рис. А.1. Формат заголовка IPv4
■ Значение 4-разрядного поля версия (version) равно 4. Это версия протокола IP, используемая с начала 80-х.
■ В поле длина заголовка (header length) указывается полная длина IP-заголовка, включающая любые параметры, описанные 32-разрядными словами. Максимальное значение этого 4-разрядного поля равно 15, и это значение задает максимальную длину IP-заголовка 60 байт. Таким образом, если заголовок занимает фиксированные 20 байт, то 40 байт остается на различные параметры.
■ 16-разрядное поле кода дифференцированных сервисов (Differentiated Services Code Point, DSCP) (RFC 2474 [82]) и 2-разрядное поле явного уведомления о загруженности сети (Explicit Congestion Notification, ECN) (RFC 3168 [100]) заменили 8-разрядное поле тип службы (сервиса) (type-of-service, TOS), которое описывалось в RFC 1349 [5]. Все 8 разрядов этого поля можно установить с помощью параметра сокета IP_TOS (см. раздел 7.6), хотя ядро может перезаписать любое установленное нами значение при проведении политики Diffserv или реализации ECN.
■ Поле общая длина (total length) имеет размер 16 бит и задает полную длину IP- дейтаграммы в байтах, включая заголовок IPv4. Количество данных в дейтаграмме равно значению этого поля минус длина заголовка, умноженная на 4. Данное поле необходимо, поскольку некоторые каналы передачи данных заполняют кадр до некоторой минимальной длины (например, Ethernet) и возможна ситуация, когда размер действительной IP-дейтаграммы окажется меньше требуемого минимума.
■ 16-разрядное поле идентификации (identification) является уникальным для каждой IP-дейтаграммы и используется при фрагментации и последующей сборке в единое целое (см. раздел 2.11). Значение должно быть уникальным для каждого сочетания отправителя, получателя и протокола в течение того времени, пока дейтаграмма может находиться в пути. Если пакет ни при каких условиях не может подвергнуться фрагментации (например, установлен бит DF), нет необходимости устанавливать значение этого поля.
■ Бит DF (флаг запрета фрагментации), бит MF (указывающий, что есть еще фрагменты для обработки) и 13-разрядное поле смещения фрагмента (fragment offset) также используются при фрагментации и последующей сборке в единое целое. Бит DF полезен при обнаружении транспортной MTU (раздел 2.11).
■ 8-разрядное поле времени жизни (time-to-live, TTL) устанавливается отправителем и уменьшается на единицу каждым последующим маршрутизатором, через который проходит дейтаграмма. Дейтаграмма отбрасывается маршрутизатором, который уменьшает данное поле до нуля. При этом время жизни любой дейтаграммы ограничивается 255 пересылками. Обычно по умолчанию данное поле имеет значение 64, но можно сделать соответствующий запрос и изменить его с помощью параметров сокета
IP_TTL
и
IP_MULTICAST_TTL
(см. раздел 7.6).
■ 8-разрядное поле протокола (protocol) определяет тип данных, содержащихся в IP-дейтаграмме. Характерные значения этого поля — 1 (ICMPv4), 2 (IGMPv4), 6 (TCP) и 17 (UDP). Эти значения определены в реестре IANA «Номера протоколов».
■ 16-разрядная контрольная сумма заголовка (header checksum) вычисляется для IP-заголовка (включая параметры). В качестве алгоритма вычисления используется стандартный алгоритм контрольных сумм для Интернета — простое суммирование 16-разрядных обратных кодов, как показано в листинге 28.11.