首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在epoll_wait之后更新epoll事件?

如何在epoll_wait之后更新epoll事件?
EN

Stack Overflow用户
提问于 2015-10-28 02:38:16
回答 1查看 1.2K关注 0票数 1

下面的代码摘录(经过大量修改以删除不重要的细节)在一组罕见且特殊的情况下失败。

代码语言:javascript
复制
struct epoll_event *events = calloc(MAXEVENTS+1, sizeof(struct epoll_event));
struct sockaddr_in in_addr;
socklen_t in_len = sizeof in_addr;

while(1)
  {
  int n = epoll_wait(efd,events, MAXEVENTS, -1);
  for(int i=0; i<n; i++)
    {
    struct epoll_event *evI = &events[i];
    uint64 u64 = evI->data.u64;
    int type = u64>>32, fd=u64, fdx = fd;

    if(type == -1)
      {
      while((fd = accept4(fdx, &in_addr, &in_len, SOCK_NONBLOCK|SOCK_CLOEXEC))>-1)
        {
        setNew_Connection(efd, fd);
        storeAddrPort(fd, &in_addr, &in_len);
        }
      }
    else
      {
      if(evI->events&(EPOLLERR|EPOLLHUP|EPOLLRDHUP)){closeConnection(fd);}
      if(evI->events&EPOLLOUT)  //process out data stuff
      else if(evI->events&EPOLLIN) //process in data stuff and possibly close a different connection.
      }
    }
  }

侦听套接字由-1evI->data.u64的上部进行区分。

setNew_Connection通常会做一些接受的事情,比如将新套接字添加到epoll等。

使用EPOLLET

现在,所有这些都非常出色,除非在以下情况下,它会失败,因为events只在epoll_wait中更新,因此连接闭包在返回到while(1)循环顶部之前不会影响n事件。

  1. epoll_wait在events struct表中使用排队的3个事件解除阻塞。
  2. 第一个事件(n=0)是传入的数据,之后代码决定关闭连接(例如文件描述符8),因为它不再需要。
  3. 第二个事件(n=1)是一个传入的新连接。accept4分配fd:8,因为它最近已经可用。setNew_Connection将其添加到epoll列表中。
  4. 第三个事件是步骤2中关闭的连接的传入数据,即fd:8,但是它不再有效,因为最初的fd:8连接已经关闭,而当前fd:8用于不同的连接。

我希望我已充分解释了这个问题。问题是,当连接关闭时,events表中的排队事件在代码返回到epoll_wait之前不会更新。我如何编码来解决这个问题呢?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-10-28 20:30:39

Orel给了我答案,但我想我会发布完整的代码解决方案。而不是

close(fd)

我使用

代码语言:javascript
复制
shutdown(fd,SHUT_RDWR);
FDS[FDSL++] = fd;

shutdown防止数据被读取或写入,但实际上并不关闭套接字。FDS[FDSL++] = fd;存储fd,以便在完成n个事件之后,可以使用while(FDSL)close(FDS[--FDSL];关闭fd。

代码语言:javascript
复制
int FDS[MAXEVENTS],FDSL=0;

struct epoll_event *events = calloc(MAXEVENTS+1, sizeof(struct epoll_event));
struct sockaddr_in in_addr;
socklen_t in_len = sizeof in_addr;

while(1)
  {
  int n = epoll_wait(efd,events, MAXEVENTS, -1);
  for(int i=0; i<n; i++)
    {
    struct epoll_event *evI = &events[i];
    uint64 u64 = evI->data.u64;
    int type = u64>>32, fd=u64, fdx = fd;

    if(type == -1)
      {
      while((fd = accept4(fdx, &in_addr, &in_len, SOCK_NONBLOCK|SOCK_CLOEXEC))>-1)
        {
        setNew_Connection(efd, fd);
        storeAddrPort(fd, &in_addr, &in_len);
        }
      }
    else
      {
      if(evI->events&(EPOLLERR|EPOLLHUP|EPOLLRDHUP)){closeConnection(fd);}
      if(evI->events&EPOLLOUT)  //process out data stuff
      else if(evI->events&EPOLLIN) //process in data stuff and possibly close a different connection.
      }
    }

  while(FDSL)close(FDS[--FDSL];
  }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33382000

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档