我想将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秒的延迟,但它没有超时。。。
ioctl()
不会执行您想要的操作。要在读取时使用超时,您需要使用poll()
或较旧的接口select()
(我会使用poll()
)。利用SO_RCVTIMEO
设置的超时可以在每次接收到新数据时被重置。因此,对于您的示例,它可能会等待长达10秒。poll()
在指定的超时后返回,告诉您是否有任何数据。一旦出现这种情况,您就可以使用非阻塞read()
读取任何内容。
您可以通过设置警报来中断系统调用来执行您想要的操作。您需要在主程序或程序初始化过程的早期进行一些基本设置:
#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
通过这种方式,您可以为一系列调用设置超时(如果连接或读取单独或总共花费的时间太长,则会超时),而不必计算每个调用花费的时间,这样您就知道等待每个后续调用需要多长时间。
您确定它在读取时被阻塞,还是可能在connect()上被阻塞?我不认为SO_RCVTIMEO(和SO_SNDTIMEO)选项会影响connect()行为。
通常,我喜欢使用非阻塞套接字(fcntl with O_NONBLOCK),然后捕获EWOULDBLOCK错误号,并使用读取集中的套接字和所需的超时值执行select()。