Добавить в цитаты Настройки чтения

Страница 273 из 399

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

14  printf("wrote 1 byte of normal datan");

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, co

 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  co

15  sleep(5);

16  for (;;) {

17   if (Sockatmark(co

18    printf("at OOB markn");

19   if ((n = Read(co

20    printf("received EOFn");

21    exit(0);

22   }

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

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

25  }

26 }

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

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_co

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 datan&quot;);

14  sleep(5);

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

16  printf(&quot;wrote 1 byte of OOB datan&quot;);

17  Write(sockfd, buff, 1024);

18  printf(&quot;wrote 1024 bytes of normal datan&quot;);