, то байт данных, на который указывает срочный указатель 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. Простая программа для получения внеполосных данных