как использовать таймауты с read () на сокете в c ++ на Unix - PullRequest
0 голосов
/ 06 февраля 2012

Я хочу использовать read () с ioctl (), но хочу контролировать, сколько времени чтения должно ждать, используя тайм-аут.Любая идея о том, как это сделать?

до сих пор я знаю следующее:

//CLIENT.cpp
struct timeval tv={1,0};
setsockopt( mysocket, SOL_SOCKET, SO_RCVTIMEO, (char *) &tv, sizeof(tv));
connect(mysocket, &sock_dest, sizeof(struct sockaddr));
len = read(mysocket, buffer, 10);

Я пытался использовать 5-секундную задержку на сервере, но она не прервалась ...

Ответы [ 3 ]

4 голосов
/ 06 февраля 2012

ioctl() не будет делать то, что вы хотите. Чтобы использовать таймаут для чтения, вам нужно использовать poll() или более старый интерфейс select() (я бы использовал poll()). Время ожидания, установленное с помощью SO_RCVTIMEO, может сбрасываться при каждом получении новых данных. Итак, для вашего примера это может подождать до 10 секунд. poll() возвращается через указанное время, сообщая, есть ли какие-либо данные. Как только это так, вы можете просто прочитать все, что есть, используя неблокирующую read().

2 голосов
/ 06 февраля 2012

Вы можете делать то, что хотите, установив будильник для прерывания системного вызова. Вам нужна базовая настройка где-то в основном или в начале процесса инициализации программы:

#include <signal.h>

sig_atomic_t alarm_counter;

void alarm_handler(int signal) {
    alarm_counter++;
}

void setup_alarm_handler() {
    struct sigaction sa;
    memset(&sa, 0, sizeof(sa));
    sa.sa_handler = alarm_handler;
    sa.flags = 0;
    if (sigaction(SIGALRM, &sa, 0) < 0)
        die("Can't establish signal handler");
}
// call setup_alarm_handler in main

Затем вы можете использовать его как:

alarm(10); // set a 10 second timeout
(len = connect(mysocket, &sock_dest, sizeof(struct sockaddr))) < 0 ||
(len = read(mysocket, buffer, 10));
alarm(0); // cancel alarm if it hasn't happened yet
if (len == -1 && errno == EINTR)
    // timed out before any data read
else if (len == -1)
    // other error

Таким образом, вы можете иметь тайм-аут для последовательности вызовов (это будет тайм-аут, если соединение или чтение занимает слишком много времени по отдельности или в целом), вместо того, чтобы выяснять, сколько времени занял каждый вызов, так что вы знаете, сколько ждать каждого последующего звонка.

0 голосов
/ 06 февраля 2012

Вы уверены, что он блокирует чтение или, возможно, блокирует соединение ()? Я не верю, что параметры SO_RCVTIMEO (и SO_SNDTIMEO) влияют на поведение connect ().

В общем, мне нравится использовать неблокирующие сокеты (fcntl с O_NONBLOCK), а затем перехватывать EWOULDBLOCK errno и делать select () с сокетом в наборе чтения и желаемым временем ожидания.

...