2010-05-20 139 views
80

我怎样才能尝试从超时套接字读取数据? 我知道,select,pselect,poll,有一个超时字段,但是使用它们会禁用tcp reno栈中的“tcp fast-path”。Linux:有没有从超时套接字读取或recv?

我唯一的想法是使用的recv(FD,...,MSG_DONTWAIT)在一个循环

+0

也有使用线程的选择:)但信号线仍然需要 – osgx 2010-06-04 13:36:05

回答

147

可以使用setsockopt函数来设置超时的接收操作:

SO_RCVTIMEO

设置指定 输入 功能等待,直到它的最大时间量的超时值完成。它 接受与 秒数和微秒 指定上多久 等待极限,用于将输入到操作完成 以timeval结构。如果接收操作已阻塞为 这么多时间而不 接收附加数据,应当 返回与部分计数或errno 设置为[EAGAIN]或者如果没有 数据被接收[EWOULDBLOCK]。此 选项的默认值为零,这表示 接收操作不应超时。 该选项采用timeval结构。 请注意,并非所有实施 都允许设置此选项。

// LINUX 
struct timeval tv; 
tv.tv_sec = timeout_in_seconds; 
tv.tv_usec = 0; 
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv); 

// WINDOWS 
DWORD timeout = timeout_in_seconds * 1000; 
setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof timeout); 

// MAC OS X (identical to Linux) 
struct timeval tv; 
tv.tv_sec = timeout_in_seconds; 
tv.tv_usec = 0; 
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv); 

Reportedly在Windows这应该叫bind之前完成。我已经通过实验证实,它可以完成之前或bind在Linux和OS X.后

+2

它是否适用于Linux 2.6 tcp? UDP? – osgx 2010-05-31 12:16:58

+5

是的。非常感谢 – osgx 2010-06-04 13:33:48

+0

这在Windows上看不到。 – Mendes 2016-04-15 18:32:06

0

SIGALRM安装一个处理程序,那么之前经常阻塞recv()使用alarm()ualarm()。如果警报消失,recv()将返回一个错误errno设置为EINTR

+8

报警(和信号)是错误的方式本任务。如果我想使用tcp快速路径,比我需要最小的延迟。信号很慢。 – osgx 2010-06-04 13:35:17

+1

@osgx信号仅在超时时发生。 – 2015-11-03 23:04:30

13

这里有一个简单的代码在C添加时间来使用轮询您的recv函数:

struct pollfd fd; 
int ret; 

fd.fd = mySocket; // your socket handler 
fd.events = POLLIN; 
ret = poll(&fd, 1, 1000); // 1 second for timeout 
switch (ret) { 
    case -1: 
     // Error 
     break; 
    case 0: 
     // Timeout 
     break; 
    default: 
     recv(mySocket,buf,sizeof(buf), 0); // get your data 
     break; 
} 
-1

LINUX

struct timeval tv; 
tv.tv_sec = 30;  // 30 Secs Timeout 
tv.tv_usec = 0;  // Not init'ing this can cause strange errors 
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv,sizeof(struct timeval)); 

WINDOWS

DWORD timeout = SOCKET_READ_TIMEOUT_SEC * 1000; 
setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout)); 

注意:你已经把这个设置之前bind()函数调用正确的运行

+2

这个问题已经在几年前回答了。你的解决方案带来了什么新的价值? – 2017-08-30 10:39:32

+0

你已经把这个设置放在bind()函数调用之前,正确运行这部分在ans里没有提到 – vivek 2017-09-08 10:17:58

相关问题