当套接字关闭时,epoll 不会发出事件信号
epoll does not signal an event when socket is close
我有一个侦听器套接字,我得到的每个新连接都会像这样将它添加到 epoll:
int connfd = accept(listenfd, (struct sockaddr *)&clnt_addr, &clnt_addr_len);
ev.events = EPOLLIN | EPOLLET | EPOLLONESHOT | EPOLLHUP;
ev.data.fd = connfd;
epoll_ctl(epollfd, EPOLL_CTL_ADD, connfd, &ev)
收到新数据时,epoll 信号 'EPOLLIN' 事件 - 正如预期的那样。
遇到这样的情况,我查阅了全部资料如下:
long read = 0;
do {
read = recv(events[n].data.fd, buffer, sizeof (buffer), 0);
} while (read > 0);
如果我粗暴地或正常地断开连接,epoll 不会发出事件信号。
每个线程中的代码运行,这就是我正在使用的 EPOLLET。
所以我的问题是:
- 我需要做什么才能获得此活动?
- 我需要怎么做才能关闭socket才不会造成资源泄露?
您的尝试存在一些问题。
你不应该使用 EPOLLONESHOT
除非你知道你在做什么并且你真的需要它。它会禁用向 epoll 实例报告任何其他事件,直到您使用 EPOLL_CTL_MOD
.
再次启用它为止
您不应使用 EPOLLHUP
来确定连接是否已关闭。 EPOLLHUP
事件可能会在从套接字输入流中读取所有数据之前引发,即使客户端正常断开也是如此。我建议你只使用 EPOLLIN
。如果没有剩余输入(因为强制或正常断开连接),read()
将 return 0
(EOF) 并且您可以关闭套接字。
您的 read()
调用将阻塞读取线程并消耗整个流,直到 EOF(连接关闭)。使用 epoll()
的重点是不必使用 while ( read(...) > 0 )
循环。
您不应该使用 EPOLLET
,因为“代码 运行 是多线程的”,而是因为您需要它。您可以在没有 edge-triggered 模式的情况下编写多线程代码。使用 EPOLLET
需要透彻了解阻塞和 non-blocking I/O 之间的区别。您很容易 运行 陷入陷阱(如手册中所述),例如 edge-triggered 饥饿。
我有一个侦听器套接字,我得到的每个新连接都会像这样将它添加到 epoll:
int connfd = accept(listenfd, (struct sockaddr *)&clnt_addr, &clnt_addr_len);
ev.events = EPOLLIN | EPOLLET | EPOLLONESHOT | EPOLLHUP;
ev.data.fd = connfd;
epoll_ctl(epollfd, EPOLL_CTL_ADD, connfd, &ev)
收到新数据时,epoll 信号 'EPOLLIN' 事件 - 正如预期的那样。
遇到这样的情况,我查阅了全部资料如下:
long read = 0;
do {
read = recv(events[n].data.fd, buffer, sizeof (buffer), 0);
} while (read > 0);
如果我粗暴地或正常地断开连接,epoll 不会发出事件信号。
每个线程中的代码运行,这就是我正在使用的 EPOLLET。
所以我的问题是:
- 我需要做什么才能获得此活动?
- 我需要怎么做才能关闭socket才不会造成资源泄露?
您的尝试存在一些问题。
你不应该使用
再次启用它为止EPOLLONESHOT
除非你知道你在做什么并且你真的需要它。它会禁用向 epoll 实例报告任何其他事件,直到您使用EPOLL_CTL_MOD
.您不应使用
EPOLLHUP
来确定连接是否已关闭。EPOLLHUP
事件可能会在从套接字输入流中读取所有数据之前引发,即使客户端正常断开也是如此。我建议你只使用EPOLLIN
。如果没有剩余输入(因为强制或正常断开连接),read()
将 return0
(EOF) 并且您可以关闭套接字。您的
read()
调用将阻塞读取线程并消耗整个流,直到 EOF(连接关闭)。使用epoll()
的重点是不必使用while ( read(...) > 0 )
循环。您不应该使用
EPOLLET
,因为“代码 运行 是多线程的”,而是因为您需要它。您可以在没有 edge-triggered 模式的情况下编写多线程代码。使用EPOLLET
需要透彻了解阻塞和 non-blocking I/O 之间的区别。您很容易 运行 陷入陷阱(如手册中所述),例如 edge-triggered 饥饿。