将超时设置为recv功能

时间:2015-05-22 11:14:04

标签: c++ sockets visual-c++ recv

我使用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)
      {
      ...
      }

如何在一些时间后问recv函数返回?

3 个答案:

答案 0 :(得分:23)

在不使用recv()的情况下在select()上设置超时的另一种方法是使用setsockopt()设置套接字的SO_RCVTIMEO选项(在支持它的平台上)。 / p>

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

答案 1 :(得分:8)

您应该检查select的返回值。如果超时超时,select将返回0,因此您应检查错误,并仅在recv返回正值时致电select

  

成功时,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...
    }
}

答案 2 :(得分:1)

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

http://linux.die.net/man/3/fd_set