select.select() 函数参数中的文件描述符不能为负整数错误。

5

我正在为个人使用编写一个简单的Python 3.6.1聊天应用程序。在使用select.select时,我遇到了以下错误:

Traceback (most recent call last):
  File "C:\Users\Nathan Glover\Google Drive\MAGENTA Chat\chat_server.py", line 
27, in <module>
    ready_to_read,ready_to_write,in_error = select.select(SOCKET_LIST,[],[],0)
ValueError: file descriptor cannot be a negative integer (-1)

这里是代码:
    ready_to_read,ready_to_write,in_error = select.select(SOCKET_LIST,[],[],0)

完全是因为我不太了解select,而且文档也没有帮助。有人能解释一下为什么会发生这种情况吗?


尝试在select调用之前插入“print SOCKET_LIST”。很可能SOCKET_LIST中的某个文件描述符为负数。 - Jeremy Friesner
3
我尝试了那个方法,但它会无限制地打印出 [<socket.socket fd=660, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('0.0.0.0', 9009)>]。 - Jeffrey thesliderturtle
如果在选择调用之前打印(没有任何 -1),我会看到相同的结果,但是如果在捕获错误后打印,那么我会看到 fd=-1 - David Winiecki
5个回答

8

我知道这个问题被问了很久。但是我想让提问者和其他人知道这里的问题。 这里的问题是SOCKET_LIST必须包含一个不存在的套接字连接,该连接可能早已断开。如果你将这样的连接传递给select函数,它会出现这个错误。

ValueError: file descriptor cannot be a negative integer (-1)

一种简单的解决方案是将 select 块放在 try - except 块内,并捕获错误。发现错误时,可以从 SOCKET_LIST 中删除连接。

1
我也遇到了这个问题,并且已经解决了。 希望这个答案能够帮助大家。 关闭的套接字的文件描述符将变为-1。 因此,最有可能是在slelect的输入参数列表中存在关闭的套接字。 也就是说,在select周期中,当您的判断逻辑添加到rlist、wlist、xlist时,这些逻辑可能存在问题。 尽管简单而粗暴的方法是使用try-except来删除具有负fileno的套接字。 但我建议您重新组织您的逻辑。如果您不确定,请使用rlist、wlist和xlist代替列表以避免列表中出现重复元素。

0

如果您没有正确初始化服务器套接字,则可能无法正常工作。 请尝试使用以下代码:

HOST = '127.0.0.1' # '' =  all available interfaces
PORT = 9009        # Arbitrary non-privileged port
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 
sock.setblocking(0) # non-blocking I/O
sock.bind((HOST, PORT))
sock.listen(5) # queue up as many as 5 connect requests 
SOCKET_LIST = [sock]

0

这是因为文件描述符之一是负值。 要解决这个问题 检查文件描述符是否为负数,并将其从列表中删除。

for sock in SOCKET_LIST:
    if sock.fileno() == -1:
        SOCKET_LIST.remove(sock)
ready_read, ready_write, error = sel.select(SOCKET_LIST, [], [], 0)

-1

我知道我来晚了,但这个问题似乎是由于在传递给selectSOCKET_LIST中存在一个关闭的文件描述符引起的,另一种解决方案是在调用select之前从SOCKET_LIST中删除关闭的文件。 这个解决方案的时间复杂度为O(n^2),但比尝试和捕获要好。

for sock in SOCKET_LIST:
    # Remove file descriptor if closed
    if sock.fileno < 0:
        SOCKET_LIST.remove(sock)

ready_to_read,ready_to_write,in_error = select.select(SOCKET_LIST,[],[],0)

它将每次迭代SOCKET_LIST,但socket.fd < 0是非常罕见的; try-catch会像什么都没有一样运行,直到某个套接字的fd < 0 - Abhi747

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接