Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/63.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jsp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何在epoll\u等待后更新epoll事件?_C_Events_Epoll - Fatal编程技术网

C 如何在epoll\u等待后更新epoll事件?

C 如何在epoll\u等待后更新epoll事件?,c,events,epoll,C,Events,Epoll,我有下面的代码摘录(大量修改以删除不重要的细节),它在罕见的特定情况下失败 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(in

我有下面的代码摘录(大量修改以删除不重要的细节),它在罕见的特定情况下失败

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.
      }
    }
  }
struct epoll_event*events=calloc(MAXEVENTS+1,sizeof(struct epoll_event));
结构sockaddr\u in\u addr;
socklen_t in_len=in_addr的大小;
而(1)
{
int n=epoll_wait(efd,events,MAXEVENTS,-1);
对于(int i=0;idata.u64;
int type=u64>>32,fd=u64,fdx=fd;
如果(类型==-1)
{
而((fd=accept4(fdx、in_addr、in_len、SOCK_NONBLOCK、SOCK_CLOEXEC))>-1)
{
设置新的_连接(efd、fd);
存储地址端口(fd、in地址和in地址);
}
}
其他的
{
如果(evI->events&(EPOLLERR | EPOLLHUP | EPOLLRDHUP)){closeConnection(fd);}
if(evI->events&epolout)//处理数据填充
else if(evI->events&EPOLLIN)//处理数据填充并可能关闭不同的连接。
}
}
}
侦听套接字通过
evI->data.u64的上部的
-1
进行区分

setNew\u Connection
执行通常的接受操作,如向epoll添加新套接字等

使用了EPOLLET

现在,它工作得非常出色,但在以下情况下失败,因为
events
仅在
epoll\u wait
中更新,因此连接关闭不会影响
n
事件,直到返回
while(1)
循环的顶部

  • epoll\u wait
    取消阻塞,事件结构表中有3个事件排队
  • 第一个事件(n=0)是传入的数据,之后代码决定关闭连接(例如文件描述符8),因为不再需要它
  • 第二个事件(n=1)是传入的新连接。
    accept4
    将fd:8分配为最近可用。
    setNew\u connection
    将其添加到epoll列表中
  • 第三个事件是步骤2中关闭的连接的传入数据。即fd:8,但它不再有效,因为原始fd:8连接已关闭,而当前fd:8用于不同的连接

  • 我希望我已经充分解释了这个问题。问题是当连接关闭时,
    events
    表中的排队事件不会更新,直到代码返回到
    epoll\u wait
    。我如何编码解决这个问题?

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

    我用

    shutdown(fd,SHUT_RDWR);
    FDS[FDSL++] = fd;
    
    shutdown
    阻止读取或写入更多数据,但实际上不会关闭套接字。
    FDS[FDSL++]=fd;
    存储fd,以便在n个事件完成后,可以在(FDSL)关闭(FDS[--FDSL];

    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];
      }
    
    intfds[MAXEVENTS],FDSL=0;
    struct epoll_event*events=calloc(MAXEVENTS+1,sizeof(struct epoll_event));
    结构sockaddr\u in\u addr;
    socklen_t in_len=in_addr的大小;
    而(1)
    {
    int n=epoll_wait(efd,events,MAXEVENTS,-1);
    对于(int i=0;idata.u64;
    int type=u64>>32,fd=u64,fdx=fd;
    如果(类型==-1)
    {
    而((fd=accept4(fdx、in_addr、in_len、SOCK_NONBLOCK、SOCK_CLOEXEC))>-1)
    {
    设置新的_连接(efd、fd);
    存储地址端口(fd、in地址和in地址);
    }
    }
    其他的
    {
    如果(evI->events&(EPOLLERR | EPOLLHUP | EPOLLRDHUP)){closeConnection(fd);}
    if(evI->events&epolout)//处理数据填充
    else if(evI->events&EPOLLIN)//处理数据填充并可能关闭不同的连接。
    }
    }
    while(FDSL)close(FDS[--FDSL];
    }
    
    Orel给了我答案,但我想我会发布完整的代码解决方案。而不是

    关闭(fd)

    我用

    shutdown(fd,SHUT_RDWR);
    FDS[FDSL++] = fd;
    
    shutdown
    阻止读取或写入更多数据,但实际上不会关闭套接字。
    FDS[FDSL++]=fd;
    存储fd,以便在n个事件完成后,可以在(FDSL)关闭(FDS[--FDSL];

    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];
      }
    
    intfds[MAXEVENTS],FDSL=0;
    struct epoll_event*events=calloc(MAXEVENTS+1,sizeof(struct epoll_event));
    结构sockaddr\u in\u addr;
    socklen_t in_len=in_addr的大小;
    而(1)
    {
    int n=epoll_wait(efd,events,MAXEVENTS,-1);
    对于(int i=0;idata.u64;
    int type=u64>>32,fd=u64,fdx=fd;
    如果(类型==-1)
    {
    而((fd=accept4(fdx、in_addr、in_len、SOCK_NONBLOCK、SOCK_CLOEXEC))>-1)
    {
    设置新的_连接(efd、fd);
    存储地址端口(fd、in地址和in地址);
    }
    }
    其他的
    {
    如果(evI->events&(EPOLLERR | EPOLLHUP | EPOLLRDHUP)){closeConnection(fd);}
    if(evI->events&epolout)//处理数据填充
    else if(evI->events&EPOLLIN)//处理数据填充并可能关闭不同的连接。
    }
    }
    while(FDSL)close(FDS[--FDSL];
    }
    
    您可以将连接标记为关闭,并在事件处理程序之后执行关闭循环。您可以将连接标记为关闭,并在事件处理程序之后执行关闭循环。