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

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

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

15  exit(0);

16 }

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

//oob/tcprecv04.c

 1 #include "unp.h"

 2 int

 3 main(int argc, char **argv)

 4 {

 5  int listenfd, connfd, n, on = 1;

 6  char buff[100];

 7  if (argc == 2)

 8   listenfd = Tcp_listen(NULL, argv[1], NULL);

 9  else if (argc == 3)

10   listenfd = Tcp_listen(argv[1], argv[2], NULL);

11  else

12   err_quit("usage- tcprecv04 [ <host> ] <port#>");

13  Setsockopt(listenfd, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on));

14  connfd = Accept(listenfd, NULL, NULL);

15  sleep(5);

16  for (;;) {

17   if (Sockatmark(connfd))

18    printf("at OOB mark\n");

19   if ((n = Read(connfd, buff, sizeof(buff) - 1)) == 0) {

20    printf("received EOF\n");

21    exit(0);

22   }

23   buff[n] = 0; /* завершающий нуль */

24   printf("read %d bytes: %s\n", n; buff);

25  }

26 }

Включение параметра сокета SO_OOBINLINE

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

Вызов функции sleep после вызова функции accept

14-15
 После того как выполнена функция
accept
, получатель переходит в спящее состояние, что позволяет получить все данные, посланные отправителем. Это позволяет нам продемонстрировать, что функция read останавливается на отметке внеполосных данных, даже если в приемном буфере сокета имеются дополнительные данные.

Считывание всех отправленных данных

16-25
 В программе имеется цикл, в котором вызывается функция
read
и выводятся полученные данные. Но перед вызовом функции
read
функция
sockatmark
проверяет, находится ли указатель буфера на отметке внеполосных данных.

После выполнения этой программы мы получаем следующий результат:

freebsd4 % <b>tcprecv04 6666</b>

read 3 bytes: 123

at OOB mark

read 2 bytes: 45

received EOF

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

read
возвращает только три байта, так как была обнаружена отметка внеполосных данных. Следующий считанный байт — это байт, содержащий внеполосные данные (его значение равно 4), так как мы дали ядру указание поместить внеполосные данные вместе с обычными.

Пример: дополнительные свойства внеполосных данных

Теперь мы покажем другой столь же простой пример, иллюстрирующий две дополнительные особенности внеполосных данных, о которых мы уже упоминали ранее.

1. TCP посылает уведомление об отправке внеполосных данных (их срочный указатель), даже если поток данных остановлен функциями управления потоком.

2. Принимающий процесс может получить уведомление о том, что отправитель отослал внеполосные данные (с помощью сигнала

SIGURG
или функции
select
) до того, как эти данные фактически прибудут. Если после получения этого уведомления процесс вызывает функцию
recv
, задавая флаг
MSG_OOB
, а внеполосные данные еще не прибыли, то будет возвращена ошибка
EWOULDBLOCK
.

В листинге 24.8 приведена программа отправки.

Листинг 24.8. Программа отправки

//oob/tcpsend05.c

 1 #include &quot;unp.h&quot;

 2 int

 3 main(int argc, char **argv)

 4 {

 5  int sockfd, size;

 6  char buff[16384];

 7  if (argc != 3)

 8   err_quit(&quot;usage: tcpsend04 &lt;host&gt; &lt;port#&gt;&quot;);

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

10  size = 32768;

11  Setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &amp;size, sizeof(size));

12  Write(sockfd, buff, 16384);

13  printf(&quot;wrote 16384 bytes of normal data\n&quot;);

14  sleep(5);

15  Send(sockfd, &quot;a&quot;, 1, MSG_OOB);

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

17  Write(sockfd, buff, 1024);

18  printf(&quot;wrote 1024 bytes of normal data\n&quot;);

273
{"b":"225366","o":1}
ЛитМир: бестселлеры месяца