Книга: UNIX: разработка сетевых приложений
Пример: особенности отметки внеполосных данных
Разделы на этой странице:
Пример: особенности отметки внеполосных данных
Далее мы приводим простой пример, иллюстрирующий следующие две особенности отметки внеполосных данных:
1. Отметка внеполосных данных всегда указывает на один байт дальше конечного байта обычных данных. Это означает, что, когда внеполосные данные получены вместе с обычными, функция sockatmark
возвращает 1, если следующий считываемый байт был послан с флагом MSG_OOB
. Если параметр SO_OOBINLINE
не включен (состояние по умолчанию), то функция sockatmark
возвращает 1, когда следующий байт данных является первым байтом, посланным следом за внеполосными данными.
2. Операция считывания всегда останавливается на отметке внеполосных данных [128, с. 519–520]. Это означает, что если в приемном буфере сокета 100 байт, но только 5 из них расположены перед отметкой внеполосных данных, то когда процесс выполнит функцию read
, запрашивая 100 байт, возвратятся только 5 байт, расположенные до этой отметки. Эта вынужденная остановка на отметке позволяет процессу вызвать функцию sockatmark
, которая определит, находится ли указатель буфера на отметке внеполосных данных.
В листинге 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 datan");
11 Send(sockfd, "4", 1, MSG_OOB);
12 printf("wrote 1 byte of OOB datan");
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, 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 markn");
19 if ((n = Read(connfd, buff, sizeof(buff) - 1)) == 0) {
20 printf("received EOFn");
21 exit(0);
22 }
23 buff[n] = 0; /* завершающий нуль */
24 printf("read %d bytes: %sn", n; buff);
25 }
26 }
Включение параметра сокета SO_OOBINLINE
13
Мы хотим принимать внеполосные данные вместе с обычными данными, поэтому нам нужно включить параметр SO_OOBINLINE
. Но если мы будем ждать, когда выполнится функция accept и установит этот параметр для присоединенного сокета, трехэтапное рукопожатие завершится и внеполосные данные могут уже прибыть. Поэтому нам нужно установить этот параметр еще для прослушиваемого сокета, помня о том, что все параметры прослушиваемого сокета наследуются присоединенным сокетом (см. раздел 7.4).
Вызов функции sleep после вызова функции accept
14-15
После того как выполнена функция accept
, получатель переходит в спящее состояние, что позволяет получить все данные, посланные отправителем. Это позволяет нам продемонстрировать, что функция read останавливается на отметке внеполосных данных, даже если в приемном буфере сокета имеются дополнительные данные.
Считывание всех отправленных данных
16-25
В программе имеется цикл, в котором вызывается функция read
и выводятся полученные данные. Но перед вызовом функции read
функция sockatmark
проверяет, находится ли указатель буфера на отметке внеполосных данных.
После выполнения этой программы мы получаем следующий результат:
freebsd4 % tcprecv04 6666
read 3 bytes: 123
at OOB mark
read 2 bytes: 45
received EOF
Хотя принимающий TCP получил все посланные данные, первый вызов функции read
возвращает только три байта, так как была обнаружена отметка внеполосных данных. Следующий считанный байт — это байт, содержащий внеполосные данные (его значение равно 4), так как мы дали ядру указание поместить внеполосные данные вместе с обычными.
- Пример установочного скрипта
- Резервное копирование базы данных InterBase
- Firebird РУКОВОДСТВО РАЗРАБОТЧИКА БАЗ ДАННЫХ
- Пример из практики
- Резервное копирование многофайловых баз данных
- Восстановление из резервных копий многофайловых баз данных
- Владелец базы данных
- ЧАСТЬ IV. База данных и ее объекты.
- Перевод базы данных InterBase 6.x на 3-й диалект
- Типы данных для работы с датой и временем
- Практическая работа 53. Запуск Access. Работа с объектами базы данных
- Обзор основных причин повреждения базы данных