Простой пример использования сигнала SIGURG
Простой пример использования сигнала 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 ");
11 sleep(1);
12 Send(sockfd, "4", 1, MSG_OOB);
13 printf("wrote 1 byte of OOB data ");
14 sleep(1);
15 Write(sockfd, "56", 2);
16 printf("wrote 2 bytes of normal data ");
17 sleep(1);
18 Send(sockfd, "7", 1, MSG_OOB);
19 printf("wrote 1 byte of OOB data ");
20 sleep(1);
21 Write(sockfd, "89", 2);
22 printf("wrote 2 bytes of normal data ");
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. Простая программа для получения внеполосных данных
//oob/tcprecv01.c
1 #include "unp.h"
2 int listenfd, connfd;
3 void sig_urg(int);
4 int
5 main(int argc, char **argv)
6 {
7 int n;
8 char buff[100];
9 if (argc == 2)
10 listenfd = Tcp_listen(NULL, argv[1], NULL);
11 else if (argc == 3)
12 listenfd = Tcp_listen(argv[1], argv[2], NULL);
13 else
14 err_quit("usage: tcprecv01 [ <host> ] <port#>");
15 connfd = Accept(listenfd, NULL, NULL);
16 Signal(SIGURG, sig_urg);
17 Fcntl(connfd, F_SETOWN, getpid());
18 for (;;) {
19 if ((n = Read(connfd, buff, sizeof(buff) - 1)) == 0) {
20 printf("received EOF ");
21 exit(0);
22 }
23 buff[n] = 0; /* завершающий нуль */
24 printf("read bytes: %s ", n, buff);
25 }
26 }
27 void
28 sig_urg(int signo)
29 {
30 int n;
31 char buff[100];
32 printf("SIGURG received ");
33 n = Recv(connfd, buff, sizeof(buff) - 1, MSG_OOB);
34 buff[n] = 0; /* завершающий нуль */
35 printf("read OOB byte: %s ", n, buff);
36 }
Установка обработчика сигнала и владельца сокета
16-17 Устанавливается обработчик сигнала SIGURG и функция fcntl задает владельца сокета для данного соединения.
ПРИМЕЧАНИЕ
Обратите внимание, что мы не задаем обработчик сигнала, пока не завершается функция accept. Существует небольшая вероятность того, что внеполосные данные могут прибыть после того, как TCP завершит трехэтапное рукопожатие, но до завершения функции accept. Внеполосные данные мы в этом случае потеряем. Допустим, что мы установили обработчик сигнала перед вызовом функции accept, а также задали владельца прослушиваемого сокета (который затем стал бы владельцем присоединенного сокета). Тогда, если внеполосные данные прибудут до завершения функции accept, наш обработчик сигналов еще не получит значения для дескриптора connfd. Если данный сценарий важен для приложения, следует инициализировать connfd, «вручную» присвоив этому дескриптору значение -1, добавить в обработчик проверку равенства connfd ==-1 и при истинности этого условия просто установить флаг, который будет проверяться в главном цикле после вызова accept. За счет этого главный цикл сможет узнать о поступлении внеполосных данных и считать их. Можно заблокировать сигнал на время вызова accept, но при этом программа будет страдать от всех возможных ситуаций гонок, описанных в разделе 20.5.
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, после чего получатель считывает один байт, содержащий внеполосные данные.
Более 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);Прежде чем рассматривать эту функцию с позиций администратора ресурсов, надо сначала понять, что это за
11.3.2. Простой пример stat()
11.3.2. Простой пример stat() Рассмотрим простую программу, которая отображает информацию из lstat() для каждого имени файла, переданного в аргументе. Она иллюстрирует, как использовать значения, возвращенные семейством функций stat(). 1: /* statsamp.с */ 2: 3: /* Для каждого имени файла,
Простой пример использования функции select
Простой пример использования функции select Теперь мы переделаем код нашего получателя внеполосных данных и вместо сигнала SIGURG будем использовать функцию select. В листинге 24.3 показана принимающая программа.Листинг 24.3. Принимающая программа, в которой (ошибочно)
Простой пример
Простой пример Конечно, приведенный выше пример довольно сложен — ведь он написан на машинном языке и в шестнадцатиричном виде. Но его можно упростить, ведь отладчик в Windows XP поддерживает как ASCII-символы, так и язык «Ассемблера».Вот упрощением мы сейчас и займемся.
Пример простой хранимой процедуры
Пример простой хранимой процедуры Настало время создать первую хранимую процедуру и на ее примере изучить процесс создания хранимых процедур. Но для начала следует сказать несколько слов о том, как работать с хранимыми процедурами Дело в том, что своей славой
5.3.1. Учебный пример: SMTP, простой протокол передачи почты
5.3.1. Учебный пример: SMTP, простой протокол передачи почты В примере 5.7. иллюстрируется транзакция SMTP (Simple Mail Transfer Protocol — простой протокол передачи почты), который описан в спецификации RFC 2821. В данном примере строки, начинающиеся с С:, отправляются почтовым транспортным
5.3.1. Учебный пример: SMTP, простой протокол передачи почты
5.3.1. Учебный пример: SMTP, простой протокол передачи почты В примере 5.7. иллюстрируется транзакция SMTP (Simple Mail Transfer Protocol — простой протокол передачи почты), который описан в спецификации RFC 2821. В данном примере строки, начинающиеся с C:, отправляются почтовым транспортным
ПРИМЕР ПРОСТОЙ ПРОГРАММЫ НА ЯЗЫКЕ СИ
ПРИМЕР ПРОСТОЙ ПРОГРАММЫ НА ЯЗЫКЕ СИ Давайте рассмотрим простую программу на языке Си. Следует сразу сказать, что такой пример нужен нам лишь для выявления некоторых основных черт любой программы, написанной на языке Си. Далее мы дадим пояснения к каждой строке, но, перед
Пример 10-14. Простой цикл while
Пример 10-14. Простой цикл while #!/bin/bashvar0=0LIMIT=10while [ "$var0" -lt "$LIMIT" ]do echo -n "$var0 " # -n подавляет перевод строки. var0=`expr $var0 + 1` # допускается var0=$(($var0+1)).doneechoexit
Пример 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 # неверное число
Пример 25-1. Простой массив
Пример 25-1. Простой массив #!/bin/basharea[11]=23area[13]=37area[51]=UFOs# Массивы не требуют, чтобы последовательность элементов в массиве была непрерывной.# Некоторые элементы массива могут оставаться неинициализированными.# "Дыркм" в массиве не являются ошибкой.echo -n "area[11] = "echo ${area[11]} #
20.1.1. Простой способ использования команды shift
20.1.1. Простой способ использования команды shift Для обработки каждого передаваемого аргумента достаточно воспользоваться командой shift. Ниже приводится соответствующий сценарий:$ pg opt2#!/bin/sh# oPt21оор=0while [ $# -ne 0 ] # цикл выполняется до тех пор, пока остаются аргументы doecho $1shift