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
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 [
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
28 sig_urg(int signo)
29 {
30 int n;
31 char buff[100];
32 printf("SIGURG received\n");
33 n = Recv(connfd, buff, sizeof(buff) - 1, MSG_OOB);
34 buff[n] = 0; /* завершающий нуль */