Добавить в цитаты Настройки чтения

Страница 154 из 399

Мы также рассказываем о том, как определить, сколько данных находится в приемном буфере сокета и как использовать с сокетами стандартную библиотеку ввода-вывода С, и обсуждаем более совершенные способы ожидания событий.

14.2. Тайм-ауты сокета

Существует три способа установки тайм-аута для операции ввода-вывода через сокет.

1. Вызов функции alarm, которая генерирует сигнал SIGALRM, когда истекает заданное время. Это подразумевает обработку сигналов, которая может варьироваться от одной реализации к другой. К тому же такой подход может стать помехой другим существующим вызовам функции alarm в данном процессе.

2. Блокирование при ожидании ввода-вывода в функции select, имеющей встроенное ограничение времени, вместо блокирования в вызове функции read или write.

3. Использование более новых параметров сокета — SO_RCVTIMEO и SO_SNDTIMEO. Проблема при использовании этого подхода заключается в том, что не все реализации поддерживают новые параметры сокетов.

Все три технологии работают с функциями ввода и вывода (такими как read, write и их вариациями, например recvfrom и sendto), но нам также хотелось бы иметь технологию, работающую с функцией co

Теперь мы представим примеры применения всех трех технологий.

Тайм-аут для функции co

В листинге 14.1[1] показана наша функция co

Листинг 14.1. Функция co

//lib/co

 1 #include "unp.h"

 2 static void co

 3 int

 4 co

 5 {

 6  Sigfunc *sigfunc;

 7  int n;

 8  sigfunc = Signal(SIGALRM, co

 9  if (alarm(nsec) != 0)

10   err_msg("co

11  if ((n = co

12   close(sockfd);

13   if (errno == EINTR)

14    errno = ETIMEDOUT;

15  }

16  alarm(0); /* отключение alarm */

17  Signal(SIGALRM, sigfunc); /* восстанавливаем прежний обработчик

                                 сигнала */

18  return (n);

19 }

20 static void

21 co

22 {

23  return; /* просто прерываем co

24 }

8 Для SIGALRM устанавливается обработчик сигнала. Текущий обработчик сигнала (если таковой имеется) сохраняется, и таким образом мы можем восстановить его в конце функции.

9-10 Таймер для процесса устанавливается на время (число секунд), заданное вызывающим процессом. Возвращаемое значение функции alarm — это число секунд, остающихся в таймере для процесса (если он уже установлен для процесса) в настоящий момент или 0 (если таймер не был установлен прежде). В первом случае мы выводим сообщение с предупреждением, поскольку мы стираем предыдущую установку таймера (см. упражнение 14.2).

11-15 Вызывается функция co

16-18 Таймер при обнулении выключается, и восстанавливается предыдущий обработчик сигналов (если таковой имеется).

20-24 Обработчик сигнала просто возвращает управление. Предполагается, что это прервет ожидание функции co

Одним из важных моментов в этом примере является то, что мы всегда можем сократить период ожидания для функции co

Другой важный момент в данном примере — то, что мы используем возможность прерывания системного вызова (co

1

Все исходные коды программ, опубликованные в этой книге, вы можете найти по адресу http://www.piter.com.