Литмир - Электронная Библиотека
Содержание  
A
A

 8  sockfd = Tcp_connect(argv[1], argv[2]);

 9  Write(sockfd, "123", 3);

10  printf("wrote 3 bytes of normal data\n");

11  Send(sockfd, "4", 1, MSG_OOB);

12  printf("wrote 1 byte of OOB data\n");

13  Write(sockfd, "5", 1);

14  printf("wrote 1 byte of normal data\n");

15  Send(sockfd,. "6", 1, MSG_OOB);

16  printf("wrote 1 byte of OOB data\n");

17  Write(sockfd, "7", 1);

18  printf("wrote 1 byte of normal data\n");

19  exit(0);

20 }

В данном случае отправка данных происходит без пауз, что позволяет быстро переслать данные собеседнику.

Принимающая программа идентична программе, приведенной в листинге 24.7, где вызывается функция

sleep
, которая после установления соединения переводит получателя в спящее состояние на 5 с, чтобы позволить данным прибыть на принимающий TCP. Ниже приводится результат выполнения этой программы:

freebsd4 % <b>tcprecv06 5555</b>

read 5 bytes: 12345

at OOB mark

read 2 bytes: 67

received EOF

Прибытие второго байта внеполосных данных (

6
) изменяет отметку, которая ассоциировалась с первым прибывшим байтом внеполосных данных (
4
). Как мы сказали, для конкретного соединения TCP допускается только одна отметка внеполосных данных.

24.4. Резюме по теме внеполосных данных TCP

Все приведенные до сих пор примеры, иллюстрирующие использование внеполосных данных, были весьма тривиальны. К сожалению, когда мы начинаем учитывать возможные проблемы, связанные с согласованием во времени при пересылке внеполосных данных, ситуация заметно усложняется. В первую очередь, нужно осознать, что концепция внеполосных данных подразумевает передачу получателю трех различных фрагментов информации:

1. Сам факт того, что отправитель вошел в срочный режим. Принимающий процесс получает уведомление об этом либо с помощью сигнала

SIGURG
, либо с помощью функции
select
. Это уведомление передается сразу же после того, как отправитель посылает байт внеполосных данных, поскольку, как показано в листинге 24.9, TCP посылает уведомление, даже если поток каких-либо данных от сервера к клиенту остановлен функциями управления потоком. В результате получения такого уведомления получатель может входить в определенный специальный режим обработки последующих данных.

2. Позиция байта, содержащего внеполосные данные, то есть расположение этого байта по отношению к остальным данным, посланным отправителем, иначе говоря, отметка внеполосных данных.

3. Фактическое значение внеполосного байта. Поскольку TCP является потоковым протоколом, который не интерпретирует данные, посланные приложением, это может быть любое 8-разрядное значение.

Говоря о срочном режиме TCP, мы можем рассматривать флаг URG как уведомление, а срочный указатель как внеполосную отметку.

Проблемы, связанные с концепцией внеполосных данных, сформулированы в следующих пунктах:

1. Для каждого соединения имеется только один срочный указатель.

2. Для каждого соединения допускается только одна отметка внеполосных данных.

3. Для каждого соединения имеется только один однобайтовый буфер, предназначенный для внеполосных данных (это имеет значение, только если внеполосные данные не считываются вместе с обычными данными).

В листинге 24.10 показано, что вновь прибывшая отметка внеполосных данных отменяет все предыдущие отметки, до которых принимающий процесс еще не дошел. Если внеполосные данные считываются вместе с обычными данными, то в случае прибытия новых внеполосных данных предыдущие не теряются, но теряются их отметки.

Типичный пример использования внеполосных данных — протокол Rlogin, задействующий эту концепцию в ситуации, когда клиент прерывает программу, выполняемую на стороне сервера [111, с. 393–394]. Сервер должен сообщить клиенту, что нужно сбросить все данные, принятые от сервера, буферизованные и предназначенные для вывода на терминал. Сервер посылает клиенту специальный байт внеполосных данных, указывая тем самым, что необходимо сбросить все полученные данные. Когда клиент получает сигнал

SIGURG
, он просто считывает данные из сокета, пока не встречает отметку внеполосных данных, после чего он сбрасывает все данные вплоть до этой отметки. (В [111, с. 398–401] показан пример подобного использования внеполосных данных вместе с выводом программы
tcpdump
.) Если в этом сценарии сервер посылает несколько внеполосных байтов, следующих с небольшими промежутками друг за другом, то такая последовательность не оказывает влияния на клиента, поскольку тот просто сбрасывает все данные, расположенные до последней отметки внеполосных данных.

В итоге можно сказать, что польза применения внеполосных данных зависит от того, для каких целей они служат в приложении. Если их назначение в том, чтобы сообщить собеседнику о необходимости сбросить все обычные данные, расположенные до отметки, то утрата промежуточных внеполосных данных и их отметок не повлечет никаких последствий. Но если потеря внеполосных данных недопустима, то эти данные следует получать вместе с обычными данными. Более того, байты, посланные как внеполосные данные, требуется каким-то образом отличать от обычных данных, так как промежуточные отметки могут быть перезаписаны при получении новых внеполосных данных. Telnet, например, посылает свои собственные команды в потоке обычных данных между клиентом и сервером, но ставит перед этими командами байт, содержащий 255 (поэтому для отправки этого значения требуется послать последовательно два байта, содержащих 255). Эти байты позволяют отличить команды сервера от обычных пользовательских данных, но при этом для обнаружения команд сервера требуется, чтобы клиент и сервер обрабатывали каждый байт данных.

24.5. Резюме

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

В API сокетов срочный режим TCP сопоставляется внеполосным данным. Отправитель входит в срочный режим, задавая флаг

MSG_OOB
при вызове функции send. Последний байт данных, переданных с помощью этой функции, считается внеполосным байтом. Приемник получает уведомление о том, что его TCP получил новый срочный указатель. Это происходит либо с помощью сигнала
SIGURG
, либо с помощью функции
select
, которая указывает, что на сокете возникла исключительная ситуация. По умолчанию TCP извлекает байт с внеполосными данными и помещает его в специальный однобайтовый буфер для внеполосных данных, откуда принимающий процесс считывает его с помощью вызова функции
recv
с флагом
MSG_OOB
. Имеется другой вариант — получатель может включить параметр сокета
SO_OOBINLINE
, и тогда внеполосный байт остается в потоке обычных данных. Независимо от того, какой метод используется принимающей стороной, уровень сокета поддерживает отметку внеполосных данных в потоке данных, и операция считывания остановится, когда дойдет до этой отметки. Чтобы определить, достигнута ли эта отметка, принимающий процесс использует функцию
sockatmark
.

275
{"b":"225366","o":1}