Python3 中 EPOLLHUP 事件是如何触发的?
如题。对端发送 close 关闭 socket,服务端的 EPOLLHUP 为啥不执行呢?
前提:没有被 IN/OUT 覆盖,我是把它写在 if 判断的第一个位置。我打印了 event 的值,发现只有 1(in)、4(out)、5( in | out),并没有发现 EPOLLHUP 16 的迹象。
dalao 们,有遇到过么,麻烦指点下
Python3 中 EPOLLHUP 事件是如何触发的?
对端 close 的话 epoll 返回 EPOLLRDHUP
EPOLLHUP 是对端 reset 了连接(假设 tcp )
EPOLLHUP 事件在 Python 的 select.epoll 模块中表示“挂起”(hang-up),它通常由底层文件描述符的连接被关闭触发。具体来说,当对端关闭了连接(比如 TCP 连接的对端调用了 close() 或 shutdown()),本地套接字会收到这个事件。在 epoll 中,EPOLLHUP 常常与 EPOLLIN 或 EPOLLRDHUP(如果支持)一起出现,表明连接已不可用。
在代码中,你可以这样检测 EPOLLHUP:
import select
import socket
# 创建非阻塞 TCP 服务器套接字
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setblocking(0)
server.bind(('0.0.0.0', 8080))
server.listen(5)
epoll = select.epoll()
epoll.register(server.fileno(), select.EPOLLIN)
try:
while True:
events = epoll.poll(1)
for fileno, event in events:
if fileno == server.fileno():
# 接受新连接
conn, addr = server.accept()
conn.setblocking(0)
epoll.register(conn.fileno(), select.EPOLLIN)
elif event & select.EPOLLHUP:
# 连接被对端关闭
print(f"Connection on fd {fileno} hung up")
epoll.unregister(fileno)
# 关闭套接字(这里需要从某个字典中获取套接字对象)
# sock.close()
elif event & select.EPOLLIN:
# 可读事件处理
pass
finally:
epoll.unregister(server.fileno())
epoll.close()
server.close()
注意:EPOLLHUP 触发后,通常应该注销并关闭对应的套接字。实际应用中,你需要维护一个文件描述符到套接字对象的映射(比如用字典),以便在事件触发时能正确操作套接字。
简单总结:EPOLLHUP 表示连接被对端关闭,处理时记得清理资源。
epoll 主动 modify 触发
这个我知道,按道理是这样的,不过我在 python3.7 里面,就是不触发,哭
请问具体是如何 modify 的呢,在什么情况下
没写过 3 的, 但是处理过 py2.7 的, 估计大同小异 可以参考下我的连接池实现代码:
github.com/baidu/CUP/blob/master/cup/net/async/conn.py 重点是 poll 方法那一块
while not self._stopsign:
try:
events = self._epoll.poll(1)
except IOError as err:
if err.errno == errno.EINTR:
return
raise err
# log.debug(‘start to poll’)
for fileno, event in events:
# if it comes from the listen port, new conn
if fileno == self._bind_sock.fileno():
newsock, addr = self._bind_sock.accept()
self._handle_new_conn(newsock, addr)
elif event & select.EPOLLIN:
try:
self._handle_new_recv(self._fileno2context[fileno])
except KeyError:
log.info(‘socket already closed’)
elif event & select.EPOLLOUT:
try:
self._handle_new_send(self._fileno2context[fileno])
except KeyError:
log.info(‘socket already closed’)
elif (event & select.EPOLLHUP) or (event & select.EPOLLERR):
# FIXME: consider if we need to release net msg resources
if event & select.EPOLLHUP:
log.info(’–EPOLLHUP–’)
else:
log.info(’–EPOLLERR–’)
try:
self.cleanup_error_context(
self._fileno2context[fileno]
)
except KeyError:
log.info(‘socket already closed’)
V2EX 不知道怎么显示代码, 直接 github 看吧
好的,感谢

