我正在尝试创建一个应用程序,该应用程序创建一个套接字并打印传入的数据(出现在套接字中)。 select is the preferred method to work with sockets所以我这样写:
#!/usr/bin/python3
from select import select
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('localhost', 2345))
s.setblocking(False) # True did not change anything
#s.settimeout(2) # same behavior if uncommented
s.send(("give me data\n").encode("latin1"))
while True:
readers, writers, err = select([s], [s], [])
if s in readers:
data = s.recv(1024)
print(data)
# some kind of sleep here?
但这是代码示例占用一个CPU内核的100%。
在具有无阻塞套接字的情况下,等待没有无休止循环的套接字中的数据的正确方法是什么?我需要它来检查连接是否仍然有效。有一个类似的问题CPU reaching 100% usage with select in python,但没有明确解释为什么需要某种睡眠。
答案 0 :(得分:2)
调用它的方式(readers, writers, err = select([s], [s], [])
),如果可读或可写,则会立即返回。但是您只检查它是否可读。
在大多数情况下,套接字可能是可写的,这正是您所要知道的。
另一种可能性是在某处添加time.sleep(0.02)
,例如G。当您在该循环中不执行任何其他操作时。然后,不应该担心20毫秒的额外延迟(但是,这并不干净)。
答案 1 :(得分:2)
选择最常见的用途是仅考虑rlist
和timeout
参数。对于您的示例代码,它应该是:
while True:
readers, writers, err = select([s], [], [])
if s in readers:
data = s.recv(1024)
print(data)
wlist
参数仅在应用程序可能必须写入大数据时使用。在这种情况下,仅将要写入套接字的数据排队,并将套接字添加到wlist
。当select
返回并且有一些内容要写入套接字时,程序将尝试写入,如果仍有内容,则将其再次推送到队列中(请注意:必须推送到头部...),然后套接字保留在wlist
中。如果所有内容均已写入并且队列为空,那么将从wlist
中删除套接字。
在上文中,队列可以是真正的双端队列,也可以是简单的bytes
缓冲区或任何其他允许在两端添加字节的容器。每个插槽应有一个。