在侦听套接字上我设置了EPOLLIN位但是在客户端连接上我将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)
...
Run Code Online (Sandbox Code Playgroud)
这就是我测试位的方式:
if ((events & EPOLLIN) == EPOLLIN)
...
if ((events & EPOLLOUT) == EPOLLOUT)
...
Run Code Online (Sandbox Code Playgroud)
我也尝试过:
if (events & EPOLLIN)
...
if (events & EPOLLOUT)
...
Run Code Online (Sandbox Code Playgroud)
两种方式都是真的!
但是,每当我在epoll fd上调用epoll_wait时,返回的活动文件描述符ALWAYS都设置了两个位,即使send()没有返回EAGAIN但是当我尝试recv()时它返回EAGAIN.
当recv()返回EAGAIN时,我不知道我应该做什么,我应该删除EPOLLOUT标志还是什么?
@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));
}
Run Code Online (Sandbox Code Playgroud)
然后我调用epoll_wait():
if (flags & DATA_IN) {
/* try to read which is impossible because this is never set. */
Run Code Online (Sandbox Code Playgroud)
Nik*_*sov 28
我觉得你倒退了.EPOLLOUT除非您EAGAIN从写入尝试获得,否则不要包括,并在成功将字节写入套接字时将其删除.
这基本上意味着只要套接字内核发送缓冲区中有空间,套接字总是可写的.
您有两个数据流 - 输入和输出.
您正在等待输入,包括EPOLLIN在标志中.如果epoll_wait(2)没有设置从该标志返回,则在某个其他套接字上发生某个事件,或者此套接字有其他事件.除非您收到错误(意味着您仍然对套接字上的输入感兴趣),请将标志保留在事件中.
你不必等待输出(因为它是你的动作),你只需要写入套接字,但是如果你溢出套接字发送缓冲区,你EAGAIN将从send(2)或来write(2).在这种情况下,你开始等待输出是可能的(内核耗尽套接字发送缓冲区,从而为你发送更多的空间)包括EPOLLOUT.一旦得到,将挂起的输出字节写入套接字,如果成功,EPOLLOUT则从事件中删除.
现在EPOLLET表示边缘触发等待,这意味着您的所需事件只会在每次状态更改时发出一次信号(例如从"无输入"到"有输入").在这种模式下,你应该在循环中读取输入字节,直到你得到EAGAIN.
希望这可以帮助.
| 归档时间: |
|
| 查看次数: |
9602 次 |
| 最近记录: |