我有一个多线程Python 3应用程序,在线程#1上接受TCP套接字通信。线程#2将检查所有当前连接是否有任何要接收的内容,然后采取相应措施。
所以,目前我有一个名为all_connections
的列表,它是一个已接受套接字连接对象的列表。
使用for connection in all_connections:
我可以遍历所有连接对象。我知道我使用conn.recv(256)
来检查是否有任何东西可以在这个套接字上恢复。这会阻止循环,直到有东西可以接收吗?我事先设置了conn.setblocking(1)
,虽然我不确定这是否是最好的解决方法:
以下是一些示例代码:
self.all_connections = [] # init a list to hold connection objs
while 1:
try:
conn, address = self.socket.accept()
conn.setblocking(1) # non blocking
except Exception as e:
continue
self.all_connections.append(conn) # Save the connection object
while True:
for connection in self.all_connections:
received = connection.recv(256)
return
所以,我只对实际发送过某些东西的连接感兴趣,因为我最有可能发回一些东西。
我知道我可以使用select.select
来检查套接字上是否有任何内容可以接收,但这并不能帮助我引用特定的连接。
答案 0 :(得分:2)
是的,read()
会阻止;这是默认行为。调用socket.setblocking(1)
实际上会启用阻止,这与您想要的相反。 setblocking(False)
将设置非阻止模式。非阻塞套接字上的I / O要求您使用异常处理。
更好的方法是,你已经朝着正确的方向前进,就是使用select()
。事实上,您确实知道哪个套接字发送了数据,因为select()
返回可用于读取,写入或具有错误状态的套接字列表。您向select()
传递了您感兴趣的套接字列表,并返回可用于I / O的套接字。这是函数签名:
select(...)
select(rlist, wlist, xlist[, timeout]) -> (rlist, wlist, xlist)
所以线程2中的代码看起来像这样:
from select import select
while True:
rlist, wlist, xlist = select(self.all_connections, [], [])
for connection in rlist:
received = connection.recv(256)
以上代码仅检查所有连接列表中的可读套接字,并从准备好的那些中读取数据。读取不会阻止。