Linux: 是否有带超时的从套接字读取或接收?

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

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

178357 次浏览

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

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

SO _ RCVTIMEO

设置指定 输入的最大时间量 函数等待,直到它完成 接受时间结构 秒数和微秒数 指定到 wait for an input operation to 如果接收操作已完成 被堵了这么久 receiving additional data, it shall 返回部分计数或 errno 如果没有,则设置为[ EAGAIN ]或[ EWOULDBLOCK ] data is received. The default for this 选项为零,这表明 接收操作不得超时。 此选项采用时间结构。 请注意,并非所有的实现 allow this option to be set.

// 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 上,这应该在调用 bind之前完成。我已经通过实验验证了它可以在 Linux 和 OS X 上的 bind之前或之后完成。

下面是一些简单的代码,可以使用 C 语言中的 pollrecv函数添加超时:

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;
}

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));

窗户

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

注意 : 您已经将此设置置于 bind()函数调用之前,以便正确运行

//在对 WINDOWS 进行绑定操作之后也可以工作

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