Шрифт:
В листинге 24.6 показана наша программа отправки. Она посылает три байта обычных данных, один байт внеполосных данных, а затем еще один байт обычных данных. Паузы между этими операциями отсутствуют.
В листинге 24.7 показана принимающая программа. В ней не используется ни функция
select
, ни сигнал SIGURG
. Вместо этого в ней вызывается функция sokatmark
, определяющая положение байта внеполосных данных. Листинг 24.6. Программа отправки
//oob/tcpsen04.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: tcpsend04 <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 Send(sockfd, "4", 1, MSG_OOB);
12 printf("wrote 1 byte of OOB data\n");
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
проверяет, находится ли указатель буфера на отметке внеполосных данных.