C++ 将超时设置为 recv 函数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30395258/
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
Setting timeout to recv function
提问by vico
I read from socket using recv
function. I have problem when no data available for reading. My programm just stops. I found that I can set timeout using select
function. But looks that timeout affects select function itself and recv
that goes after select still waits uncontinuously.
我使用recv
函数从套接字读取。当没有可供阅读的数据时,我遇到了问题。我的程序就停止了。我发现我可以使用select
函数设置超时。但是看起来超时会影响 select 函数本身,recv
并且在 select 之后仍然会不连续地等待。
fd_set set;
struct timeval timeout;
FD_ZERO(&set); /* clear the set */
FD_SET(s, &set); /* add our file descriptor to the set */
timeout.tv_sec = SOCKET_READ_TIMEOUT_SEC;
timeout.tv_usec = 0;
int rv = select(s, &set, NULL, NULL, &timeout);
if((recv_size = recv(s , rx_tmp , bufSize ,0)) == SOCKET_ERROR)
{
...
}
How to ask recv
function return after some timout?
recv
超时后如何要求函数返回?
采纳答案by Nemanja Boric
You should check return value of select
. select
will return 0
in case timeout expired, so you should check for error and call recv
only if select
returned positive value:
您应该检查 的返回值select
。select
将0
在超时到期时返回,因此您应该检查错误并recv
仅在select
返回正值时调用:
On success, select() and pselect() return the number of file descriptors contained in the three returned descriptor sets (that is, the total number of bits that are set in readfds, writefds, exceptfds) which may be zero if the timeout expires before anything interesting happens.
成功时,select() 和 pselect() 返回三个返回的描述符集合中包含的文件描述符的数量(即在 readfds、writefds、exceptfds 中设置的总位数),如果超时到期可能为零在任何有趣的事情发生之前。
int rv = select(s + 1, &set, NULL, NULL, &timeout);
if (rv == SOCKET_ERROR)
{
// select error...
}
else if (rv == 0)
{
// timeout, socket does not have anything to read
}
else
{
// socket has something to read
recv_size = recv(s, rx_tmp, bufSize, 0);
if (recv_size == SOCKET_ERROR)
{
// read failed...
}
else if (recv_size == 0)
{
// peer disconnected...
}
else
{
// read successful...
}
}
回答by Remy Lebeau
Another way to set a timeout on recv()
itself without using select()
is to use setsockopt()
to set the socket's SO_RCVTIMEO
option (on platforms that support it).
另一种在recv()
不使用的情况下设置超时的方法select()
是使用setsockopt()
设置套接字的SO_RCVTIMEO
选项(在支持它的平台上)。
On Windows, the code would look like this:
在 Windows 上,代码如下所示:
DWORD timeout = SOCKET_READ_TIMEOUT_SEC * 1000;
setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout));
//...
recv_size = recv(s, rx_tmp, bufSize, 0);
if (recv_size == SOCKET_ERROR)
{
if (WSAGetLastError() != WSAETIMEDOUT)
//...
}
On other platforms, the code would look like this instead:
在其他平台上,代码看起来像这样:
struct timeval timeout;
timeout.tv_sec = SOCKET_READ_TIMEOUT_SEC;
timeout.tv_usec = 0;
setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
//...
recv_size = recv(s, rx_tmp, bufSize, 0);
if (recv_size == -1)
{
if ((errno != EAGAIN) && (errno != EWOULDBLOCK))
//...
}
回答by Richard Hodges
use the FD_ISSET() macro to test whether there is data to read. If it returns false, don't do the read.
使用 FD_ISSET() 宏来测试是否有数据要读取。如果返回 false,则不进行读取。