После выполнения этой программы мы получаем следующий результат:
freebsd4 % tcprecv04 6666
read 3 bytes: 123
at OOB mark
read 2 bytes: 45
received EOF
Хотя принимающий TCP получил все посланные данные, первый вызов функции
read
возвращает только три байта, так как была обнаружена отметка внеполосных данных. Следующий считанный байт — это байт, содержащий внеполосные данные (его значение равно 4), так как мы дали ядру указание поместить внеполосные данные
вместе с обычными.
Пример: дополнительные свойства внеполосных данных
Теперь мы покажем другой столь же простой пример, иллюстрирующий две дополнительные особенности внеполосных данных, о которых мы уже упоминали ранее.
1. TCP посылает уведомление об отправке внеполосных данных (их срочный указатель), даже если поток данных остановлен функциями управления потоком.
2. Принимающий процесс может получить уведомление о том, что отправитель отослал внеполосные данные (с помощью сигнала
SIGURG
или функции
select
) до того, как эти данные фактически прибудут. Если после получения этого уведомления процесс вызывает функцию
recv
, задавая флаг
MSG_OOB
, а внеполосные данные еще не прибыли, то будет возвращена ошибка
Этот процесс устанавливает размер буфера отправки сокета равным 32 768 байт, записывает 16 384 байт обычных данных, а затем на 5 с переходит в спящее состояние. Чуть ниже мы увидим, что приемник устанавливает размер приемного буфера сокета равным 4096 байт, поэтому данные, отправленные отсылающим TCP, с гарантией заполнят приемный буфер сокета получателя. Затем отправитель посылает один байт внеполосных данных, за которым следуют 1024 байт обычных данных, и, наконец, закрывает соединение.
28 n = Recv(connfd, buff, sizeof(buff) - 1, MSG_OOB);
29 buff[n] = 0; /* завершающий пустой байт */
30 printf("read %d OOB byte\n", n);
31 }
14-20
Принимающий процесс устанавливает размер приемного буфера сокета приемника равным 4096 байт. Этот размер наследуется присоединенным сокетом после установления соединения. Затем процесс вызывает функцию
accept
, задает обработчик для сигнала
SIGURG
и задает владельца сокета. В главном цикле (бесконечном) вызывается функция
pause
.
22-31
Обработчик сигнала вызывает функцию
recv
для считывания внеполосных данных.
Если мы запускаем сначала принимающую программу, а затем программу отправки, то получаем следующий результат выполнения программы отправки:
macosx % tcpsend05 freebsd 5555
wrote 16384 bytes of normal data
wrote 1 byte of OOB data
wrote 1024 bytes of normal data
Как и ожидалось, все данные помещаются в буфер отправки сокета отправителя, и программа завершается. Ниже приведен результат работы принимающей программы: