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个事件排队accept4
将fd:8分配为最近可用。setNew\u connection
将其添加到epoll列表中我希望我已经充分解释了这个问题。问题是当连接关闭时,
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];
}
您可以将连接标记为关闭,并在事件处理程序之后执行关闭循环。您可以将连接标记为关闭,并在事件处理程序之后执行关闭循环。