gpt4 book ai didi

c++ - 阻塞套接字返回 EAGAIN

转载 作者:IT王子 更新时间:2023-10-29 00:23:23 27 4
gpt4 key购买 nike

我在 Linux 上的一个项目使用阻塞套接字。事情发生得非常连续,所以非阻塞只会让事情变得更复杂。无论如何,我发现 recv() 调用经常返回 -1,其中 errno 设置为 EAGAIN

man 页面只真正提到这种情况发生在非阻塞套接字上,这是有道理的。对于非阻塞,套接字可能可用也可能不可用,因此您可能需要重试。

什么会导致阻塞套接字发生这种情况?我可以做些什么来避免它吗?

目前,我处理它的代码看起来像这样(我让它在出错时抛出异常,但除此之外,它是一个非常简单的 recv() 包装器):

int ret;
do {
ret = ::recv(socket, buf, len, flags | MSG_NOSIGNAL);
} while(ret == -1 && errno == EAGAIN);


if(ret == -1) {
throw socket_error(strerror(errno));
}
return ret;

这是否正确? EAGAIN 条件经常被触发。

编辑:我注意到的一些可能相关的事情。

  1. 我确实使用 setsockopts() 在套接字上设置了读取超时,但它设置为 30 秒。 EAGAIN 的发生频率超过每 30 秒一次。 更正 我的调试存在缺陷,EAGAIN 的发生频率没有我想象的那么高。可能是超时触发。

  2. 对于连接,我希望能够有连接超时,所以我暂时将套接字设置为非阻塞。该代码如下所示:

    int      error = 0;
    fd_set rset;
    fd_set wset;
    int n;
    const SOCKET sock = m_Socket;

    // set the socket as nonblocking IO
    const int flags = fcntl (sock, F_GETFL, 0);
    fcntl(sock, F_SETFL, flags | O_NONBLOCK);

    errno = 0;

    // we connect, but it will return soon
    n = ::connect(sock, addr, size_addr);

    if(n < 0) {
    if (errno != EINPROGRESS) {
    return -1;
    }
    } else if (n == 0) {
    goto done;
    }

    FD_ZERO(&rset);
    FD_ZERO(&wset);
    FD_SET(sock, &rset);
    FD_SET(sock, &wset);

    struct timeval tval;
    tval.tv_sec = timeout;
    tval.tv_usec = 0;

    // We "select()" until connect() returns its result or timeout
    n = select(sock + 1, &rset, &wset, 0, timeout ? &tval : 0);
    if(n == 0) {
    errno = ETIMEDOUT;
    return -1;
    }

    if (FD_ISSET(sock, &rset) || FD_ISSET(sock, &wset)) {
    socklen_t len = sizeof(error);
    if (getsockopt(SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
    return -1;
    }
    } else {
    return -1;
    }

    done:
    // We change the socket options back to blocking IO
    if (fcntl(sock, F_SETFL, flags) == -1) {
    return -1;
    }
    return 0;

我的想法是将它设置为非阻塞,尝试连接并在套接字上进行选择,这样我就可以强制超时。 set 和 restore fcntl() 调用都成功返回,因此当此函数完成时套接字应该再次进入阻塞模式。

最佳答案

您可能在套接字上设置了非零接收超时(通过 setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,...)),因为这也会导致 recv 返回 EAGAIN

关于c++ - 阻塞套接字返回 EAGAIN,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/735249/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com