для 5-секундного тайм-аута при каждом вызове функции
recvfrom
. Если функция
recvfrom
прерывается нашим обработчиком сигнала, мы выводим сообщение об ошибке и продолжаем работу. Если получена строка от сервера, мы отключаем функцию alarm и выводим ответ.
Обработчик сигнала SIGALRM
24-28
Наш обработчик сигналов возвращает управление, прерывая блокированную функцию
recvfrom
.
Этот пример работает корректно, потому что каждый раз, когда мы устанавливаем функцию
alarm
, мы читаем только один ответ. В разделе 20.4 мы попытаемся использовать ту же технологию, но поскольку мы будем считывать множество ответов для данной функции
alarm
, возникнет ситуация гонок, которую нам придется разрешить.
Тайм-аут для функции recvfrom (функция select)
Мы демонстрируем вторую технологию для установки тайм-аута (использование функции
select
) в листинге 14.3. Здесь показана наша функция
readable_timeo
, которая ждет, когда дескриптор станет готов для чтения, но не более заданного числа секунд.
Листинг 14.3. Функция readable_timeo: ожидание, когда дескриптор станет готов для чтения
В наборе дескрипторов для чтения включается бит, соответствующий данному дескриптору. В структуре
timeval
устанавливается время (число секунд), в течение которого вызывающий процесс готов ждать.
Блокирование в функции select
11-12
Функция
select
ждет, когда дескриптор станет готов для чтения или истечет заданное время ожидания. Возвращаемое значение этой функции — это возвращаемое значение функции
select
: -1 в случае ошибки, 0, если истекло время ожидания, и положительное значение, задающее число готовых дескрипторов, если таковые появились.
Эта функция не выполняет операции чтения — она просто ждет, когда дескриптор будет готов к чтению. Следовательно, эту функцию можно использовать с любым типом сокета — TCP или UDP.
Создание аналогичной функции, называемой
writable_timeo
, тривиально. Эта функция ждет, когда дескриптор будет готов для записи.
Мы используем эту функцию в листинге 14.4, где показана еще одна версия нашей функции
dg_cli
, приведенной в листинге 8.4. Эта новая версия вызывает функцию
recvfrom
, только когда наша функция
readable_timeo
возвращает положительное значение.
Мы не вызываем функцию
recvfrom
, пока функция
readable_timeo
не сообщит нам, что дескриптор готов для чтения. Тем самым мы гарантируем, что функция
recvfrom
не заблокируется.
Листинг 14.4. Функция dg_cli, вызывающая функцию readable_timeo для установки тайм-аута
//advio/dgclitimeo1.c
1 #include "unp.h"
2 void
3 dg_cli(FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen)