C++ 将超时设置为recv功能

C++ 将超时设置为recv功能,c++,sockets,visual-c++,recv,C++,Sockets,Visual C++,Recv,我使用recv函数从套接字读取数据。当没有数据可供阅读时,我有问题。我的程序停止了。我发现我可以使用select函数设置超时。但看起来超时会影响select函数本身,select之后的recv仍在不连续地等待 fd_set set; struct timeval timeout; FD_ZERO(&set); /* clear the set */ FD_SET(s, &set); /* add our file descriptor to the set */ timeout.

我使用
recv
函数从套接字读取数据。当没有数据可供阅读时,我有问题。我的程序停止了。我发现我可以使用
select
函数设置超时。但看起来超时会影响select函数本身,select之后的
recv
仍在不连续地等待

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)
      {
      ...
      }
如何在超时后询问函数返回?

使用FD_ISSET()宏测试是否有数据要读取。如果返回false,则不进行读取


您应该检查
选择的返回值<如果超时过期,code>select
将返回
0
,因此您应该检查错误,只有在
select
返回正值时才调用
recv

成功时,select()和pselect()返回三个返回的描述符集中包含的文件描述符的数量(即在READFD、writefds和EXPEPTFDS中设置的总位数),如果超时在发生任何有趣的事情之前过期,则该数量可能为零


另一种不使用
select()
而在
recv()
本身上设置超时的方法是使用设置套接字的
SO\u RCVTIMEO
选项(在支持它的平台上)

在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)
        //...
}
在其他平台上,代码将如下所示:

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))
        //...
}

此代码示例有一个错误。。。显示以下内容的行:
int rv=select(s,&set,NULL,NULL,&timeout)应为
int rv=select(s+1,&set,NULL,NULL,&timeout)nfds
是编号最高的文件描述符+1。仅供参考,此解决方案仅适用于Windows平台,不能在Unix/Linux/OSX平台上使用。@drbobdugan:Windows不是唯一支持
的平台,尽管在其他平台上,输入参数通常是
timeval
结构。您的解决方案无法在Linux/Unix/OSX平台上运行,因为它包含类似DWORD、WSAGetLastError()等Windows构件的代码片段。在其他平台上,请使用
errno
而不是
WSAGetLastError()
。至于我的答案是以Windows为中心的,这是因为这个问题标有
visual-c++
,这意味着只使用Windows进行开发。我已经更新了我的答案,以考虑其他平台。
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))
        //...
}