如何等待任何套接字有数据?

Posted

技术标签:

【中文标题】如何等待任何套接字有数据?【英文标题】:How to wait for any socket to have data? 【发布时间】:2016-11-16 20:28:11 【问题描述】:

我正在实现一个套接字客户端,它同时打开多个套接字。任何套接字可能在不同时间有数据,我想在任何套接字有数据并且可读时执行代码。

我不确定如何实现这一点,我正在查看 select.select 但它似乎在等待所有套接字都可读。

我想避免使用多处理来处理套接字上的数据,我希望它在从每个套接字读取时是串行的,但在有可用数据时读取。

如何等待任何套接字可读?

# psudo code

sockets = [sock1, sock2, sock3]

while True:
  if len(sockets) == 0:
    break
  for sock in sockets:
    if sock.has_data():
      do_stuff(sock)
      sockets.remove(sock)
  sleep(0.1)

【问题讨论】:

select 不会等待所有套接字都可读,它会在其中一个可读时返回。 无论您做什么,如果您不想阻塞,请不要忘记将套接字设置为非阻塞。您使用的每个功能都将是一个无法用于预测未来的状态报告功能。无论select 说什么,阻塞读取可以 阻塞。 【参考方案1】:

您可以使用select.select 解决您的问题:

sockets = [sock1, sock2, sock3]
while sockets:
    rlist, _, _ = select.select(sockets, [], [])
    for sock in rlist:
        do_stuff(sock)
        sockets.remove(sock)

【讨论】:

只是不要忘记将套接字设置为非阻塞。 OP 想要阻塞,因为他在做完事情后移除了套接字。 没错,我确实想要阻止。另外,谢谢丹尼尔,我想我的尝试犯了一个错误,我能够通过选择来实现我想要的! :) 那为什么要使用select?如果你想阻塞,只需在每个套接字上调用do_stuff @DavidSchwartz 如果您这样做,您的套接字将按严格的顺序处理。即使在阻塞套接字的情况下使用选择器(选择、轮询),您也可以对任何处于可读状态的套接字做出反应【参考方案2】:

如果您使用 POSIX,请查看 select.poll

import socket
import select
p = select.poll()
s1 = socket.socket()
s2 = socket.socket()
# call connect on sockets here...
p.register(s1, select.POLLIN)
p.register(s2, select.POLLIN)
p.poll()

【讨论】:

【参考方案3】:

如果您使用的是 Python 3.4 或更新版本,标准库中有 selectors 模块。它将使用您的系统提供的“最佳”I/O 多路复用实现(选择、轮询、kqueue...)文档页面末尾有一个简单的回显服务器示例https://docs.python.org/3/library/selectors.html

还有一个backport 用于较旧的 Python 版本。

【讨论】:

以上是关于如何等待任何套接字有数据?的主要内容,如果未能解决你的问题,请参考以下文章

Chrome 在传输一定数量的数据后挂起 - 等待可用的套接字

我如何获得在 unix 域套接字中排队的数据报数量

Linux 套接字:如何让 send() 等待 recv()

中止正在等待 Read() 语句的线程(C# 套接字编程)

如何让我的异步客户端调用套接字服务器并等待响应

暂停执行直到收到套接字上的特定消息?