下面的代码摘录(经过大量修改以删除不重要的细节)在一组罕见且特殊的情况下失败。
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.
}
}
}侦听套接字由-1在evI->data.u64的上部进行区分。
setNew_Connection通常会做一些接受的事情,比如将新套接字添加到epoll等。
使用EPOLLET。
现在,所有这些都非常出色,除非在以下情况下,它会失败,因为events只在epoll_wait中更新,因此连接闭包在返回到while(1)循环顶部之前不会影响n事件。
epoll_wait在events struct表中使用排队的3个事件解除阻塞。accept4分配fd:8,因为它最近已经可用。setNew_Connection将其添加到epoll列表中。我希望我已充分解释了这个问题。问题是,当连接关闭时,events表中的排队事件在代码返回到epoll_wait之前不会更新。我如何编码来解决这个问题呢?
发布于 2015-10-28 20:30:39
Orel给了我答案,但我想我会发布完整的代码解决方案。而不是
close(fd)
我使用
shutdown(fd,SHUT_RDWR);
FDS[FDSL++] = fd;shutdown防止数据被读取或写入,但实际上并不关闭套接字。FDS[FDSL++] = fd;存储fd,以便在完成n个事件之后,可以使用while(FDSL)close(FDS[--FDSL];关闭fd。
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];
}https://stackoverflow.com/questions/33382000
复制相似问题