epoll_wait后如何更新epoll事件?
How to update epoll events after epoll_wait?
我有以下代码摘录(经过大量编辑以删除不重要的细节)在极少数情况下会失败。
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.
}
}
}
监听套接字在evI->data.u64
的上部-1
区分
setNew_Connection
执行通常的接受操作,例如将新套接字添加到 epoll 等
EPOLLET
已使用。
现在一切正常,除了在以下情况下失败,因为 events
仅在 epoll_wait
中更新,因此连接关闭不会影响 n
事件,直到返回后到 while(1)
循环的顶部。
epoll_wait
解除阻塞,事件结构 table. 中有 3 个事件排队
- 第一个事件 (n=0) 是传入数据,之后代码决定关闭连接(例如文件描述符 8),因为不再需要它。
- 第二个事件 (n=1) 是传入的新连接。
accept4
分配 fd:8,因为它最近可用。 setNew_Connection
将其添加到 epoll 列表中。
- 第三个事件是在步骤 2 中关闭的连接的传入数据。即 fd:8 但它不再有效,因为原始 fd:8 连接已关闭,当前 fd:8 是用于不同的连接。
我希望我已经充分解释了这个问题。问题是 events
table 中的排队事件在连接关闭时不会更新,直到代码 returns 到 epoll_wait
。我如何编写代码来解决这个问题?
Orel 给了我答案,但我想我会 post 完整的代码解决方案。而不是
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];
}
我有以下代码摘录(经过大量编辑以删除不重要的细节)在极少数情况下会失败。
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.
}
}
}
监听套接字在evI->data.u64
-1
区分
setNew_Connection
执行通常的接受操作,例如将新套接字添加到 epoll 等
EPOLLET
已使用。
现在一切正常,除了在以下情况下失败,因为 events
仅在 epoll_wait
中更新,因此连接关闭不会影响 n
事件,直到返回后到 while(1)
循环的顶部。
epoll_wait
解除阻塞,事件结构 table. 中有 3 个事件排队
- 第一个事件 (n=0) 是传入数据,之后代码决定关闭连接(例如文件描述符 8),因为不再需要它。
- 第二个事件 (n=1) 是传入的新连接。
accept4
分配 fd:8,因为它最近可用。setNew_Connection
将其添加到 epoll 列表中。 - 第三个事件是在步骤 2 中关闭的连接的传入数据。即 fd:8 但它不再有效,因为原始 fd:8 连接已关闭,当前 fd:8 是用于不同的连接。
我希望我已经充分解释了这个问题。问题是 events
table 中的排队事件在连接关闭时不会更新,直到代码 returns 到 epoll_wait
。我如何编写代码来解决这个问题?
Orel 给了我答案,但我想我会 post 完整的代码解决方案。而不是
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];
}