Простой пример использования функции select
Простой пример использования функции 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, buff);
25 }
26 if (FD_ISSET(connfd, &rset)) {
27 if ((n = Read(connfd, buff, sizeof(buff) - 1)) == 0) {
28 printf("received EOF ");
29 exit(0);
30 }
31 buff[n] = 0; /* завершающий нуль */
32 printf("read bytes: %s ", 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.
Чтобы решить эту проблему, нужно вызывать функцию select для проверки на наличие исключительной ситуации только после того, как будут приняты все обычные данные. В листинге 24.4 показана модифицированная версия принимающей программы из листинга 24.3. В этой версии описанный сценарий обрабатывается корректно.
Листинг 24.4. Модификация программы, приведенной в листинге 24.3. Функция select применяется для проверки исключительной ситуации корректным образом
//oob/tcprecv03.c
1 #include "unp.h"
2 int
3 main(int argc, char **argv)
4 {
5 int listenfd, connfd, n, justreadoob = 0;
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_1isten(argv[1], argv[2], NULL);
12 else
13 err_quit("usage: tcprecv03 [ <host> ] <port#>");
14 connfd = Accept(listenfd, NULL, NULL);
15 FD_ZERO(&rset);
16 FD_ZERO(&xset);
17 for (;;) {
18 FD_SET(connfd, &rset);
19 if (justreadoob == 0)
20 FD_SET(connfd, &xset);
21 Select(connfd + 1, &rset, NULL, &xset, NULL);
22 if (FD_ISSET(connfd, &xset)) {
23 n = Recv(connfd, buff, sizeof(buff) - 1, MSG_OOB);
24 buff[n] = 0; /* завершающий нуль */
25 printf("read %d OOB byte: %s ", n, buff);
26 justreadoob = 1;
27 FD_CLR(connfd, &xset);
28 }
29 if (FD_ISSET(connfd, &rset)) {
30 if ((n = Read(connfd, buff, sizeof(buff) - 1)) == 0) {
31 printf("received EOF ");
32 exit(0);
33 }
34 buff[n] = 0; /* завершающий нуль */
35 printf("read %d bytes: %s ", n, buff);
36 justreadoob = 0;
37 }
38 }
39 }
5 Мы объявляем новую переменную с именем justreadoob, которая указывает, какие данные мы считываем — внеполосные или обычные. Этот флаг определяет, нужно ли вызывать функцию select для проверки на наличие исключительной ситуации.
26-27 Когда мы устанавливаем флаг justreadoob, мы также должны выключить бит соответствующего дескриптора в наборе для проверки исключительных ситуаций.
Теперь программа работает так, как мы ожидали.
Более 800 000 книг и аудиокниг! 📚
Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОКДанный текст является ознакомительным фрагментом.
Читайте также
Простой пример
Простой пример Начнем с простого примера: наложим переход на изменение фона ссылки. Когда пользователь будет наводить на ссылку, цвет ее фона будет меняться, и мы применим переход, чтобы сделать это изменение плавным. Такого эффекта раньше можно было добиться
Простой пример функции io_read()
Простой пример функции io_read() Чтобы проиллюстрировать, как ваш администратор ресурса мог бы возвращать клиенту данные, рассмотрим простейший администратор ресурса, который всегда возвращает одну и ту же строковую константу «Здравствуй, мир! ». Даже в таком простом случае
Простой пример функции io_write()
Простой пример функции io_write() Это был простой пример функции io_read(); давайте теперь перейдем к функции io_write(). Основной камень преткновения, связанный с io_write(), — получить доступ к данным. Поскольку библиотека администратора ресурсов считывает лишь незначительную часть
Простой пример функции io_devctl()
Простой пример функции io_devctl() Клиентский вызов devctl() формально определен так:#include <sys/types.h>#include <unistd.h>#include <devctl.h>int devctl(int fd, int dcmd, void *dev_data_ptr, size_t nbytes, int *dev_info_ptr);Прежде чем рассматривать эту функцию с позиций администратора ресурсов, надо сначала понять, что это за
Глава 6 Мультиплексирование ввода-вывода: функции select и poll
Глава 6 Мультиплексирование ввода-вывода: функции select и poll 6.1. Введение В разделе 5.12 мы видели, что наш TCP-клиент обрабатывает два входных потока одновременно: стандартный поток ввода и сокет TCP. Проблема, с которой мы столкнулись, состояла в том, что пока клиент был
Максимальное число дескрипторов для функции select
Максимальное число дескрипторов для функции select Ранее мы сказали, что большинство приложений не используют много дескрипторов. Например, редко можно найти приложение, использующее сотни дескрипторов. Но такие приложения существуют, и часто они используют функцию select
Тайм-аут для функции recvfrom (функция select)
Тайм-аут для функции recvfrom (функция select) Мы демонстрируем вторую технологию для установки тайм-аута (использование функции select) в листинге 14.3. Здесь показана наша функция readable_timeo, которая ждет, когда дескриптор станет готов для чтения, но не более заданного числа
Простой пример использования сигнала SIGURG
Простой пример использования сигнала SIGURG Теперь мы рассмотрим тривиальный пример отправки и получения внеполосных данных. В листинге 24.1[1] показана программа отправки этих данных.Листинг 24.1. Простая программа отправки внеполосных данных//oob/tcpsend01.c 1 #include "unp.h" 2 int 3 main(int
Коллизии при вызове функции select
Коллизии при вызове функции select Рассматривая данный пример в 4.4BSD, мы можем исследовать еще одну проблему, которая встречается довольно редко и поэтому часто остается непонятой до конца. В разделе 16.13 [128] говорится о коллизиях (collisions), возникающих при вызове функции select
Простой пример
Простой пример Конечно, приведенный выше пример довольно сложен — ведь он написан на машинном языке и в шестнадцатиричном виде. Но его можно упростить, ведь отладчик в Windows XP поддерживает как ASCII-символы, так и язык «Ассемблера».Вот упрощением мы сейчас и займемся.
Пример: очереди сообщений Posix и функция select
Пример: очереди сообщений Posix и функция select Дескриптор очереди сообщений (переменная типа mqd_t) не является «обычным» дескриптором и не может использоваться с функциями select и poll (глава 6 [24]). Тем не менее их можно использовать вместе с каналом и функцией mq_notify. (Аналогичный
Пример оператора Select Case
Пример оператора Select Case Здесь явно не помешает пример, показывающий, как в действительности может выглядеть структура Select Case. Select Case objRol l OfFi l m.Type Case "Слайдовая" intСлайдовые = intСлайдовые + 1 Case "Цветная негативная" intЦветныеНегативные =
Пример 10-27. Простой пример сравнения строк
Пример 10-27. Простой пример сравнения строк #!/bin/bash# match-string.sh: простое сравнение строкmatch_string (){ MATCH=0 NOMATCH=90 PARAMS=2 # Функция требует два входных аргумента. BAD_PARAMS=91 [ $# -eq $PARAMS ] || return $BAD_PARAMS case "$1" in "$2") return $MATCH;; * ) return $NOMATCH;; esac}a=oneb=twoc=threed=twomatch_string $a # неверное число
20.1.1. Простой способ использования команды shift
20.1.1. Простой способ использования команды shift Для обработки каждого передаваемого аргумента достаточно воспользоваться командой shift. Ниже приводится соответствующий сценарий:$ pg opt2#!/bin/sh# oPt21оор=0while [ $# -ne 0 ] # цикл выполняется до тех пор, пока остаются аргументы doecho $1shift