Чтение онлайн

ЖАНРЫ

UNIX: разработка сетевых приложений
Шрифт:

Однако если процесс устанавливает параметр сокета

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

1. Если процесс запрашивает внеполосные данные (то

есть устанавливает флаг
MSG_OOB
), но собеседник таких данных не послал, возвращается
EINVAL
.

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

select
или сигнала
SIGURG
), и пытается считать эти данные, когда указанный байт еще не прибыл, возвращается ошибка
EWOULDBLOCK
. В такой ситуации все, что может сделать процесс, — это считать данные из приемного буфера сокета (возможно, сбрасывая данные, если отсутствует свободное место для их хранения), чтобы освободить место в буфере для приема байта внеполосных данных, посылаемых собеседником.

3. Если процесс пытается считать одни и те же внеполосные данные несколько раз, возвращается ошибка

EINVAL
.

4. Если процесс установил параметр сокета

SO_OOBINLINE
, а затем пытается считать внеполосные данные, задавая флаг
MSG_OOB
, возвращается
EINVAL
.

Простой пример использования сигнала SIGURG

Теперь мы рассмотрим тривиальный пример отправки и получения внеполосных данных. В листинге 24.1 [1] показана программа отправки этих данных.

Листинг 24.1. Простая программа отправки внеполосных данных

//oob/tcpsend01.c

1 #include "unp.h"

2 int

3 main(int argc, char **argv)

4 {

5 int sockfd;

6 if (argc != 3)

7 err_quit("usage: tcpsend01 <host> <port#>");

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

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

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

11 sleep(1);

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

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

14 sleep(1);

15 Write(sockfd, "56", 2);

16 printf("wrote 2 bytes of normal data\n");

17 sleep(1);

18 Send(sockfd, "7", 1, MSG_OOB);

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

20 sleep(1);

21 Write(sockfd, "89", 2);

22 printf("wrote 2 bytes of normal data\n");

23 sleep(1);

24 exit(0);

25 }

Отправлены 9

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

macosx % tcpsend01 freebsd 9999

wrote 3 bytes of normal data

wrote 1 byte of OOB data

wrote 2 bytes of normal data

wrote 1 byte of OOB data

wrote 2 bytes of normal data

В листинге 24.2 показана принимающая программа.

Листинг 24.2. Простая программа для получения внеполосных данных

//oob/tcprecv01.c

1 #include "unp.h"

2 int listenfd, connfd;

3 void sig_urg(int);

4 int

5 main(int argc, char **argv)

6 {

7 int n;

8 char buff[100];

9 if (argc == 2)

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

11 else if (argc == 3)

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

13 else

14 err_quit("usage: tcprecv01 [ <host> ] <port#>");

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

16 Signal(SIGURG, sig_urg);

17 Fcntl(connfd, F_SETOWN, getpid);

18 for (;;) {

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 bytes: %s\n", n, buff);

25 }

26 }

27 void

Поделиться с друзьями: