我有以下代码摘录(经过严格修改以删除不重要的细节),这些代码在罕见且特殊情况下失败。
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
中更新,因此连接闭包不会影响n
事件,直到返回到while(1)
循环的顶部。
epoll_wait
取消阻止事件结构表中排队的3个事件。accept4
指定fd:8,因为它最近可用。 setNew_Connection
将其添加到epoll列表中。我希望我已经充分解释了这个问题。问题是,在关闭连接之前,events
表中的排队事件不会更新,直到代码返回到epoll_wait
。我怎么能解决这个问题?
答案 0 :(得分:0)
Orel给了我答案,但我想我会发布完整的代码解决方案。而不是
close(fd)
我用
shutdown(fd,SHUT_RDWR);
FDS[FDSL++] = fd;
shutdown
可防止不再读取或写入数据,但实际上并未关闭套接字。 FDS[FDSL++] = fd;
存储fd,以便在n个事件完成后,可以使用while(FDSL)close(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];
}