Python socket字典与select

1 投票
2 回答
1533 浏览
提问于 2025-04-17 06:09

出于某种原因,我无法将选择的套接字与我的套接字字典匹配。下面的代码创建了一个套接字字典(确实创建了),但是当有人连接时,接受连接的部分却没有成功。它在列表'L'中找到了's',但接下来却出现了socket.error: [Errno 22] Invalid argument的错误。

listening = {}
L = []
for link in links:
    try:
        # listening
        listening[link] = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        listening[link].bind((host, routers[routername].baseport+links[link].locallink))
        listening[link].listen(backlog)
        # append routes and listen-list
        L.append(listening[link])
    except socket.error, (value,message):
        print "Could not open socket: " + message
        sys.exit(1)

# run loop
input = L
running = 1
while running:
    inputready,outputready,exceptready = select.select(input,[],[], 0)

    # Sockets loop
    for s in inputready:
        if s in L:
            # handle the server socket
            client, address = s.accept()
            input.append(client)

2 个回答

0

我觉得问题出在,当你把新连接的客户端套接字添加到(input)的时候,其实也是把它添加到了(L)里。这是因为input和L指向的是同一个列表对象。然后,当新连接的客户端套接字给你发送数据时,你试图在这个客户端套接字上调用accept(),但显然这个客户端套接字并不是一个监听套接字,所以你就会看到那个错误。

举个例子,为什么input.append(client)会把client添加到L,这里有一段我在Python解释器里的代码:

Jeremys-Mac-mini:python lcsuser1$ python
Python 2.7.1 (r271:86832, Jul 31 2011, 19:30:53) 
[GCC 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> L = [1,2,3]
>>> print L
[1, 2, 3]
>>> input = L
>>> print input
[1, 2, 3]
>>> input.append(4)
>>> print input
[1, 2, 3, 4]
>>> print L
[1, 2, 3, 4]  <-- d'oh!

要解决这个问题,你需要把这一行

input = L

替换成

input = list(L)

这样input就指向L的一个副本,而不是直接指向L本身。

0

虽然我不太确定第一次尝试中我做错了什么,但我已经解决了自己的困惑。@Jeremy的思路是对的,但有些偏差(可能是因为我描述得不够清楚)。这些套接字在s之外不会被引用,所以不需要用字典来存储。不过,select只接受列表,所以与其用其他数据类型让事情变得复杂,不如直接用列表,并引用s而不是L(反正s才是你真正需要的)

L = []
input = [sys.stdin]

for i in range(4):
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
    server.bind((host,port+i)) 
    server.listen(backlog)
    L.append(server)
    input.append(server)

running = 1
print len(L)
while running: 
    inputready,outputready,exceptready = select.select(input,[],[]) 

    for s in inputready: 
        if s in L: 
            # handle the server socket
            print "opened"
            client, address = s.accept() 
            input.append(client)
        elif s == sys.stdin: 
            # handle standard input 
            junk = sys.stdin.readline() 
            running = 0 
        else: 
            # handle all other sockets 
            data = s.recv(size)

撰写回答