我已经编写了一个简单的 TCP 服务器套接字并将 fd
添加到 epoll_cntl
。客户端连接后,accept fd
也被添加到epoll_cntl
中。
当客户端关闭时,我通过 epoll_wait
接收到一个未知事件。 epoll 事件正在接收一个事件 5(请在下面的代码中搜索字符串 “Issue seen here”。
有人可以帮助我理解为什么 epoll 会收到这样的事件吗?
这是我的代码:
int ControllerTask()
{
int retval = 0;
int res = 0;
static struct epoll_event ev;
g_epfd = epoll_create1(0);
/* Create TCP Server Socket */
retval = createTcpServerSock();
if(retval < 0)
{
return 0;
}
ev.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLERR | EPOLLHUP | EPOLLET;
ev.data.fd = g_server_fd[0];
res = epoll_ctl(g_epfd, EPOLL_CTL_ADD, g_server_fd[0], &ev);
acceptIncomingData();
}
int createTcpServerSock()
{
int retval = -1;
struct sockaddr_in addr;
int sockOpt = 0;
int reuse = 1;
do
{
if((g_server_fd[0] = socket(AF_INET, SOCK_STREAM, 0)) == 0)
{
perror("sock_failed");
return 0;
}
sockOpt = fcntl(g_server_fd[0], F_GETFL);
if(sockOpt < 0)
break;
sockOpt |= O_NONBLOCK;
if (fcntl(g_server_fd[0], F_SETFL, sockOpt) < 0)
break;
if ((retval = setsockopt(g_server_fd[0], SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse))) < 0)
break;
if ((retval = setsockopt(g_server_fd[0], SOL_SOCKET, SO_KEEPALIVE, (const char*)&reuse, sizeof(reuse))) < 0)
break;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
addr.sin_port = htons(7000);
if(bind(g_server_fd[0], (struct sockaddr *)&addr, sizeof(addr)) < 0)
{
perror("bind failed");
break;
}
listen(g_server_fd[0], SOMAXCONN);
retval = 0;
}while(0);
return retval;
}
void acceptIncomingData()
{
struct epoll_event *events;
int nfds, i, err;
int n_bytes = 0;
events = (struct epoll_event *)malloc(sizeof(struct epoll_event) * MAX_EPOLL_EVENTS);
memset(events, 0, sizeof(struct epoll_event) * MAX_EPOLL_EVENTS);
g_buff = (void *)malloc(MAX_MSG_SIZE * sizeof(char *));
memset(g_buff, 0, MAX_MSG_SIZE * sizeof(char *));
while(1) {
nfds = epoll_wait(g_epfd, events, MAX_EPOLL_EVENTS, EPOLL_WAIT_TIMEOUT);
if(!nfds)
{
continue;
}
else if(nfds < 0)
{
perror("epoll_wait");
return;
}
printf("Some data in EPOLL\n");
for(i = 0; i < nfds; i++) {
if ((events[i].events & EPOLLERR) ||
(events[i].events & EPOLLHUP))
{
printf("TCP close connection\n");
closeTcpConnection(events[i].data.fd);
return;
}
else
{
else if(EPOLLIN == events[i].events)
{
if(events[i].data.fd == g_server_fd[0])
{
acceptIncomingConns(events[i].data.fd);
printf("Accept incoming data\n");
continue;
}
n_bytes = read(events[i].data.fd, g_buff, sizeof(g_buff));
if(n_bytes == -1)
{
if(errno != EAGAIN)
{
perror("read");
}
}
else if(n_bytes == 0)
{
printf("n_bytes = 0\n");
continue;
}
else
{
printf("n_bytes = %d\n", n_bytes);
handleSocketEvents(g_buff);
}
}
else
{
/* Issue seen here: Receiving event as 5 which is not defined */
printf("In else. Event : %d\n", events[i].events);
}
}
}
}
}
}
int acceptIncomingConns(int fd)
{
/* accFd = TCP accept FD */
int accFd = 0;
int s, i;
int sockOpt = 0;
struct sockaddr in_addr;
int in_len;
struct epoll_event event;
while(1)
{
accFd = accept(fd, &in_addr, &in_len);
if(accFd == -1)
{
if((errno == EAGAIN) || (errno == EWOULDBLOCK))
{
break;
}
else
{
perror("accept");
break;
}
}
g_server_fd[1] = accFd;
sockOpt = fcntl(accFd, F_GETFL);
sockOpt |= O_NONBLOCK;
fcntl(accFd, F_SETFL, sockOpt);
event.data.fd = accFd;
event.events = EPOLLIN | EPOLLOUT | EPOLLET | EPOLLERR | EPOLLHUP;
s = epoll_ctl(g_epfd, EPOLL_CTL_ADD, accFd, &event);
}
}
void closeTcpConnection(int delFd)
{
int i = 0;
close(delFd);
g_server_fd[1] = 0;
return;
}
最佳答案
事件字段是一个位掩码。 EPOLLIN
为 1。EPOLLOUT
为 4。因此 EPOLLIN | EPOLLOUT
为 5.
所以文件描述符是可读可写的。
关于c - epoll_wait 接收未知事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49685799/