阻塞套接字返回EAGAIN [英] Blocking socket returns EAGAIN

查看:283
本文介绍了阻塞套接字返回EAGAIN的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的一个在Linux上的项目使用阻塞套接字。事情发生的如此连续无阻塞只想让事情变得更加复杂。无论如何,我发现往往是的recv()调用返回 1 错误号设置为 EAGAIN

One of my projects on Linux uses blocking sockets. Things happen very serially so non-blocking would just make things more complicated. Anyway, I am finding that often a recv() call is returning -1 with errno set to EAGAIN.

页才真正提到这种情况发生的非阻塞套接字,这是有道理的。无阻塞,插座可能会或可能无法使用,所以你可能需要重试。

The man page only really mentions this happening for non-blocking sockets, which makes sense. With non-blocking, the socket may or may not be available so you might need to try again.

什么会导致这样的情况发生了阻塞插座?我可以做任何事情,以避免它?

目前,对付我的code与它看起来像这样(我把它扔在错误的异常,但除此之外,它是围绕一个非常简单的包装的recv()

At the moment, my code to deal with it looks something like this (I have it throw an exception on error, but beyond that it is a very simple wrapper around 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 条件被击中pretty频繁。

Is this even correct? The EAGAIN condition gets hit pretty often.

编辑:有些事情我已经注意到这可能是相关的

some things which I've noticed which may be relevant.


  1. 我不使用设置的setsockopt插座上读取超时(),但它设置为30秒。在 EAGAIN 的方式过于频繁,每30秒发生一次。 修正我的调试是有缺陷的, EAGAIN 的不经常,因为我认为他们确实发生过。也许这是超时触发。

  1. I do set a read timeout on the socket using setsockopts(), but it is set to 30 seconds. the EAGAIN's happen way more often than once every 30 secs. CORRECTION my debugging was flawed, EAGAIN's don't happen as often as I thought they did. Perhaps it is the timeout triggering.

有关连,我希望能够有连接超时,所以我暂时设置套接字非阻塞。这code是这样的:

For connecting, I want to be able to have connect timeout, so I temporarily set the socket to non-blocking. That code looks like this:

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;


的想法是,我将它设置为非阻塞,尝试连接并选择在插座上,所以我可以强制超时。无论是设置和恢复的fcntl()调用成功返回,所以插座应此功能完成时阻塞模式又结束了。

The idea is that I set it to non-blocking, attempt a connect and select on the socket so I can enforce a timeout. Both the set and restore fcntl() calls return successfully, so the socket should end up in blocking mode again when this function completes.

推荐答案

这可能是因为你有一个非零(通过 setsockopt的接收超时套接字上设置(袜子,SOL_SOCKET,SO_RCVTIMEO,...) ),因为这也将导致recv的返回 EAGAIN

It's possible that you have a nonzero receive timeout set on the socket (via setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,...)) as that would also cause recv to return EAGAIN

这篇关于阻塞套接字返回EAGAIN的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆