如何在使用Python epoll的服务器中获取连接的客户端列表
我想给连接到使用Python epoll的服务器的一部分客户端发送消息。有没有什么实际的方法可以获取已连接客户端的fileno
列表呢?
1 个回答
通常,处理这个问题的方法是自己跟踪客户端。每当你接受一个新客户端时,在把它加入到 epoll
之前,也要把它添加到你的集合中。每当你断开一个客户端时,就从你的集合中移除它。
一般来说,你需要存储的最基本的信息是一个 dict
,它将套接字映射到你需要跟踪的其他信息。你可以用套接字本身、它的 weakref
,或者它的 fileno
作为键。你需要的数据通常包括读取缓冲区、写入缓冲区、对方地址(在 accept
时接收到的)、名字、用户 ID 或认证信息等。
而且我不太明白,如果你的轮询服务器没有给每个客户端套接字附加至少一个读取缓冲区,你是怎么做有用的事情的。当你收到部分消息时,你该怎么办?(更进一步,如果你打算给这些客户端发送消息,而你没有写入缓冲区,那你打算怎么做呢?)
不过,来回答你的具体问题:
从 Python 的 epoll
对象 中获取文件描述符列表是没有办法的,因为底层的 API 不支持这样做。
理论上,你可以写一个程序,遍历从 0 到你最大打开的文件描述符,然后尝试用 epoll_ctl
来操作它,并根据错误来区分。这可能是个非常糟糕的主意,但也不是不可能。你可能需要用 ctypes
调用原生函数,并且可能需要尝试不同的方式来找到合适的效果。例如,也许如果你执行 epoll_ctl(my_epoll.fileno(), EPOLL_CTL_MOD, fd, NULL)
,你会得到 ENOENT
对于未注册的文件描述符,EBADF
对于不存在的文件描述符,但对于有效的文件描述符会得到 EINVAL
(因为 event
是 NULL)。或者可能会导致程序崩溃。我不能保证有任何参数组合可以区分,但通过一些尝试和错误,你可能会找到一个。
(顺便说一下,并没有规定 epoll
必须是一个连接的客户端列表;例如,它可以是连接的客户端加上监听套接字和一个“退出”管道。)