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

на главную

Жанры

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

18-25
Процесс считывает данные из сокета и выводит каждую строку, которая возвращается функцией
read
. После того как отправитель разрывает соединение, то же самое делает и получатель.

Обработчик сигнала SIGURG

27-36
Наш обработчик сигнала вызывает функцию
printf
, считывает внеполосные данные, устанавливая флаг
MSG_OOB
, а затем выводит полученные данные. Обратите внимание, что при вызове
функции recv мы запрашиваем до 100 байт, но, как мы вскоре увидим, всегда возвращается только один байт внеполосных данных.

ПРИМЕЧАНИЕ

Как сказано ранее, вызов ненадежной функции printf из обработчика сигнала не рекомендуется. Мы делаем это просто для того, чтобы увидеть, что произойдет с нашей программой.

Ниже приведен результат, который получается, когда мы запускаем эту программу, а затем — программу для отправки внеполосных данных, приведенную в листинге 24.1.

freebsd % tcprecv01 9999

read 3 bytes: 123

SIGURG received

read 1 OOB byte: 4

read 2 bytes: 56

SIGURG received

read 1 OOB byte: 7

read 2 bytes: 89

received EOF

Результаты оказались такими, как мы и ожидали. Каждый раз, когда отправитель посылает внеполосные данные, для получателя генерируется сигнал

SIGURG
, после чего получатель считывает один байт, содержащий внеполосные данные.

Простой пример использования функции select

Теперь мы переделаем код нашего получателя внеполосных данных и вместо сигнала

SIGURG
будем использовать функцию
select
. В листинге 24.3 показана принимающая программа.

Листинг 24.3. Принимающая программа, в которой (ошибочно) используется функция select для уведомления о получении внеполосных данных

//oob/tcprecv02.c

1 #include "unp.h"

2 int

3 main(int argc, char **argv)

4 {

5 int listenfd, connfd, n;

6 char buff[100];

7 fd_set rset, xset;

8 if (argc == 2)

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

10 else if (argc ==3)

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

12 else

13 err_quit("usage: tcprecv02 [ <host> ] <port#>");

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

15 FD_ZERO(&rset);

16 FD_ZERO(&xset);

17 for (;;) {

18 FD_SET(connfd, &rset);

19 FD_SET(connfd, &xset);

20 Select(connfd + 1, &rset, NULL, &xset, NULL);

21 if (FD_ISSET(connfd, &xset)) {

22 n = Recv(connfd, buff, sizeof(buff) - 1, MSG_OOB);

23 buff[n] =0; /*
завершающий нуль */

24 printf("read OOB byte: %s\n", n, buff);

25 }

26 if (FD_ISSET(connfd, &rset)) {

27 if ((n = Read(connfd, buff, sizeof(buff) - 1)) == 0) {

28 printf("received EOF\n");

29 exit(0);

30 }

31 buff[n] = 0; /* завершающий нуль */

32 printf("read bytes: %s\n", n, buff);

33 }

34 }

35 }

15-20
Процесс вызывает функцию
select
, которая ожидает получения либо обычных данных (набор дескрипторов для чтения,
rset
), либо внеполосных (набор дескрипторов для обработки исключений,
xset
). В обоих случаях полученные данные выводятся.

Если мы запустим эту программу, а затем — программу для отправки, которая приведена в листинге 24.1, то столкнемся со следующей ошибкой:

freebsd4 % tcprecv02 9999

read 3 bytes: 123

read 1 OOB byte: 4

recv error: Invalid argument

Проблема заключается в том, что функция

select
будет сообщать об исключительной ситуации, пока процесс не считает данные, находящиеся за отметкой внеполосных данных (то есть после них [128, с. 530-531]). Мы не можем считывать внеполосные данные больше одного раза, так как после первого же их считывания ядро очищает буфер, содержащий один байт внеполосных данных. Когда мы вызываем функцию
recv
, устанавливая флаг
MSG_OOB
во второй раз, она возвращает ошибку
EINVAL
.

Поделиться:
Популярные книги

Идеальный мир для Лекаря 17

Сапфир Олег
17. Лекарь
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 17

Столичный доктор. Том III

Вязовский Алексей
3. Столичный доктор
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Столичный доктор. Том III

Камень. Книга восьмая

Минин Станислав
8. Камень
Фантастика:
фэнтези
боевая фантастика
7.00
рейтинг книги
Камень. Книга восьмая

Академия

Кондакова Анна
2. Клан Волка
Фантастика:
боевая фантастика
5.40
рейтинг книги
Академия

Князь Мещерский

Дроздов Анатолий Федорович
3. Зауряд-врач
Фантастика:
альтернативная история
8.35
рейтинг книги
Князь Мещерский

Черный Маг Императора 6

Герда Александр
6. Черный маг императора
Фантастика:
юмористическое фэнтези
попаданцы
аниме
7.00
рейтинг книги
Черный Маг Императора 6

Всплеск в тишине

Распопов Дмитрий Викторович
5. Венецианский купец
Фантастика:
попаданцы
альтернативная история
5.33
рейтинг книги
Всплеск в тишине

Камень. Книга 3

Минин Станислав
3. Камень
Фантастика:
фэнтези
боевая фантастика
8.58
рейтинг книги
Камень. Книга 3

Мастер 2

Чащин Валерий
2. Мастер
Фантастика:
фэнтези
городское фэнтези
попаданцы
технофэнтези
4.50
рейтинг книги
Мастер 2

СД. Том 17

Клеванский Кирилл Сергеевич
17. Сердце дракона
Фантастика:
боевая фантастика
6.70
рейтинг книги
СД. Том 17

Варлорд

Астахов Евгений Евгеньевич
3. Сопряжение
Фантастика:
боевая фантастика
постапокалипсис
рпг
5.00
рейтинг книги
Варлорд

Проект ’Погружение’. Том 1

Бредвик Алекс
1. Проект ’Погружение’
Фантастика:
фэнтези
рпг
постапокалипсис
5.00
рейтинг книги
Проект ’Погружение’. Том 1

Отборная бабушка

Мягкова Нинель
Фантастика:
фэнтези
юмористическая фантастика
7.74
рейтинг книги
Отборная бабушка

Дорога к счастью

Меллер Юлия Викторовна
Любовные романы:
любовно-фантастические романы
6.11
рейтинг книги
Дорога к счастью