阻塞套接字返回EAGAIN [英] Blocking socket returns 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.
-
我不使用设置
的setsockopt插座上读取超时()
,但它设置为30秒。在EAGAIN
的方式过于频繁,每30秒发生一次。 修正我的调试是有缺陷的,EAGAIN
的不经常,因为我认为他们确实发生过。也许这是超时触发。
I do set a read timeout on the socket using
setsockopts()
, but it is set to 30 seconds. theEAGAIN
'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屋!