将超时设置为recv功能

vic*_*ico 12 c++ sockets recv visual-c++

我从socket使用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)
      {
      ...
      }
Run Code Online (Sandbox Code Playgroud)

recv一些提示后如何询问函数返回?

Rem*_*eau 25

recv()不使用的情况下自行设置超时的另一种方法select()是使用setsockopt()设置套接字的SO_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)
        //...
}
Run Code Online (Sandbox Code Playgroud)

在其他平台上,代码看起来像这样:

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))
        //...
}
Run Code Online (Sandbox Code Playgroud)

  • 在其他平台上,使用`errno`而不是`WSAGetLastError()`.至于我的答案以Windows为中心的性质,这是因为问题用`visual-c ++`标记,这意味着仅限Windows开发. (3认同)

Nem*_*ric 9

你应该检查的返回值select.select0在超时到期时返回,因此您应检查错误并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...
    }
}
Run Code Online (Sandbox Code Playgroud)