[英]epoll_wait always sets EPOLLOUT bit?
On a listening socket I set the EPOLLIN
bit however on client connections I set EPOLLIN | EPOLLOUT
在侦听套接字上,我设置了
EPOLLIN
位但是在客户端连接上我设置了EPOLLIN | EPOLLOUT
EPOLLIN | EPOLLOUT
bits to struct epoll_event
like so: EPOLLIN | EPOLLOUT
位struct epoll_event
像这样:
struct epoll_event ev;
ev.data.fd = fd;
ev.events = EPOLLIN | EPOLLOUT;
if (epoll_ctl(evs->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0)
...
And this is how I test bits: 这就是我测试位的方式:
if ((events & EPOLLIN) == EPOLLIN)
...
if ((events & EPOLLOUT) == EPOLLOUT)
...
I've also tried like: 我也尝试过:
if (events & EPOLLIN)
...
if (events & EPOLLOUT)
...
Both ways are ALWAYS true! 两种方式都是真的!
However, whenever I call epoll_wait on my epoll fd, the active file descriptor returned ALWAYS has both bits set even though send() didn't return EAGAIN but when I try to recv() it returns EAGAIN. 但是,每当我在epoll fd上调用epoll_wait时,返回的活动文件描述符ALWAYS都设置了两个位,即使send()没有返回EAGAIN但是当我尝试recv()时它返回EAGAIN。
I have no idea what am I supposed to do when recv() returns EAGAIN, am I supposed to remove the EPOLLOUT
flag or what? 当recv()返回EAGAIN时,我不知道我该怎么做,我应该删除
EPOLLOUT
标志还是什么?
More code as requested by @Nikolai N Fetissov: @Nikolai N Fetissov要求的更多代码:
static int get_active_fd(events *evs, int index, sstate_t *flags)
{
uint32_t events = evs->events[index].events;
int fd = evs->events[index].data.fd;;
if ((events & EPOLLERR) == EPOLLERR || (events & EPOLLHUP) == EPOLLHUP) {
close(fd);
return -1;
}
if (events & EPOLLIN)
*flags |= DATA_IN;
return fd;
}
void sockset_add(events *evs, int fd)
{
struct epoll_event ev;
...
ev.data.fd = fd;
ev.events = EPOLLIN;
if (epoll_ctl(evs->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0)
eprintf("sockset_add(): epoll_ctl(%d) returned an error %d(%s)\n",
fd, errno, strerror(errno));
}
Then later where I call epoll_wait(): 然后我调用epoll_wait():
if (flags & DATA_IN) {
/* try to read which is impossible because this is never set. */
I think you got it backwards. 我觉得你倒退了。 Don't include
EPOLLOUT
unless you got EAGAIN
from a write attempt, and remove it when you have successfully written bytes to a socket. 除非您从写入尝试获得
EAGAIN
,否则不要包括EPOLLOUT
,并在成功将字节写入套接字时将其删除。
This basically means that socket is always writable as long as there's space in socket in-kernel send buffer. 这基本上意味着只要套接字内核发送缓冲区中有空间,套接字总是可写的。
You have two data streams - input and output . 您有两个数据流 - 输入和输出 。
You are waiting for the input by including EPOLLIN
in the flags. 您正在等待输入,
EPOLLIN
是在标志中包含EPOLLIN
。 If upon return from epoll_wait(2)
that flag is not set, then either some event happened on some other socket, or this socket had some other event. 如果从
epoll_wait(2)
返回该标志未设置,则某个事件发生在某个其他套接字上,或者此套接字有其他事件。 Leave the flag in the events unless you get an error (meaning you are still interested in the input on the socket). 除非出现错误(意味着您仍然对套接字上的输入感兴趣),否则将该标志保留在事件中。
You don't have to wait for the output (since it's your action), you just write to the socket, but if you overflow socket send buffer, you'll get EAGAIN
from send(2)
or write(2)
. 您不必等待输出(因为它是您的操作),您只需写入套接字,但如果溢出套接字发送缓冲区,您将从
send(2)
或write(2)
获得EAGAIN
。 In this case you start waiting for output to be possible (kernel draining socket send buffer thus making room for you to send more) by including EPOLLOUT
. 在这种情况下,您可以通过包含
EPOLLOUT
来开始等待输出(内核耗尽套接字发送缓冲区,从而为您发送更多内容)。 Once you get that, write your pending output bytes to the socket, and if you are successful, remove EPOLLOUT
from the events. 完成后,将挂起的输出字节写入套接字,如果成功,
EPOLLOUT
事件中删除EPOLLOUT
。
Now EPOLLET
indicates edge-triggered wait, meaning your desired event would only be signaled once per state change (like from "no input" to "there's input"). 现在,
EPOLLET
表示边缘触发等待,这意味着您的所需事件只会在每次状态更改时发出一次信号(例如从“无输入”到“有输入”)。 In this mode you are supposed to read input bytes in a loop until you get EAGAIN
. 在此模式下,您应该在循环中读取输入字节,直到获得
EAGAIN
。
Hope this helps. 希望这可以帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.