Linux:是否有超时的套接字读取或recv?

时间:2010-05-20 16:55:27

标签: c linux sockets tcp

如何尝试从超时的套接字读取数据? 我知道,select,pselect,poll,有一个超时字段,但使用它们会禁用tcp reno stack中的“tcp fast-path”。

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

5 个答案:

答案 0 :(得分:166)

您可以使用setsockopt功能设置接收操作的超时时间:

  

<强> SO_RCVTIMEO

     

设置指定的超时值   输入的最大时间量   函数等待直到完成。它   接受时间结构与   秒数和微秒数   指定多长时间的限制   等待输入操作   完成。如果接收操作有   没有这么多时间就被封锁了   收到附加数据,它应该   返回部分计数或错误   如果没有,设置为[EAGAIN]或[EWOULDBLOCK]   收到数据。默认为此   选项为零,表示a   接收操作不得超时。   此选项采用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);
Windows上的

Reportedly应该在调用bind之前完成。我已经通过实验验证了它可以在Linux和OS X上bind之前或之后完成。

答案 1 :(得分:17)

这是一个简单的代码,可以使用C中的poll来为你的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;
}

答案 2 :(得分:0)

//也适用于WINDOWS的绑定操作

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

答案 3 :(得分:-1)

SIGALRM安装处理程序,然后在常规阻止alarm()之前使用ualarm()recv()。如果闹钟响起,recv()将返回错误,errno设置为EINTR

答案 4 :(得分:-3)

<强> 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()函数调用之前设置此设置以正常运行