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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2876024/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 20:03:13  来源:igfitidea点击:

Linux: is there a read or recv from socket with timeout?

clinuxsocketstcp

提问by osgx

How can I try to read data from socket with timeout? I know, select, pselect, poll, has a timeout field, but using of them disables "tcp fast-path" in tcp reno stack.

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

The only idea I have is to use recv(fd, ..., MSG_DONTWAIT) in a loop

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

采纳答案by Robert S. Barnes

You can use the setsockoptfunction to set a timeout on receive operations:

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

SO_RCVTIMEO

Sets the timeout value that specifies the maximum amount of time an input function waits until it completes. It accepts a timeval structure with the number of seconds and microseconds specifying the limit on how long to wait for an input operation to complete. If a receive operation has blocked for this much time without receiving additional data, it shall return with a partial count or errno set to [EAGAIN] or [EWOULDBLOCK] if no data is received. The default for this option is zero, which indicates that a receive operation shall not time out. This option takes a timeval structure. Note that not all implementations allow this option to be set.

SO_RCVTIMEO

设置超时值,该值指定输入函数在完成之前等待的最长时间。它接受带有秒数和微秒数的 timeval 结构,指定等待输入操作完成的时间限制。如果接收操作阻塞了这么长时间而没有接收到额外的数据,如果没有接收到数据,它将返回部分计数或设置为 [EAGAIN] 或 [EWOULDBLOCK] 的 errno。此选项的默认值为零,表示接收操作不会超时。此选项采用 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);

Reportedlyon Windows this should be done before calling bind. I have verified by experiment that it can be done either before or after bindon Linux and OS X.

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

回答by caf

Install a handler for SIGALRM, then use alarm()or ualarm()before a regular blocking recv(). If the alarm goes off, the recv()will return an error with errnoset to EINTR.

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

回答by Abdessamad Doughri

Here's some simple code to add a time out to your recvfunction using pollin C:

这是一些简单的代码,用于在 C 中recv使用为您的函数添加超时poll

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

回答by vivek

LINUX

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

NOTE: You have put this setting before bind()function call for proper run

注意:您已将此设置放在bind()函数调用之前以正确运行

回答by cahit beyaz

// works also after bind operation for WINDOWS

// 在 WINDOWS 的绑定操作后也有效

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