我试图找到从 python 中的多个(大约 100 个)udp 数据报套接字读取的最简单方法。我看过龙卷风,但龙卷风吹捧的是 http/tcp 而不是 udp 支持。
现在我有专门用于每个 udp 套接字的线程;但是,这似乎不是很有效。
我试图找到从 python 中的多个(大约 100 个)udp 数据报套接字读取的最简单方法。我看过龙卷风,但龙卷风吹捧的是 http/tcp 而不是 udp 支持。
现在我有专门用于每个 udp 套接字的线程;但是,这似乎不是很有效。
SocketServer模块有一个内置的 UDP 服务器,带有线程和分叉选项。
另一种选择是使用select模块,它允许您只关注数据已经可供读取的套接字。
我必须承认我从未使用过它,但也许Twisted会满足您的需求。
它支持许多协议,甚至是串行连接。
我想对最初的问题添加一些评论,即使它已经有一个公认的答案。
如果您有多个需要独立处理的连接(或至少在没有太多同步的情况下进行处理),则可以为每个连接使用一个线程并进行阻塞读取。现代调度程序不会因为那个而杀死你。这是处理连接的一种相当有效的方法。如果您担心内存占用,您可以相应地减少线程的堆栈大小(不适用于 python)。
线程/进程将在大部分时间(等待新数据时)保持非忙等待状态,并且不消耗任何 CPU 时间。
如果您不想或不能使用线程,那么select
调用肯定是要走的路。这也是低级和高效的等待,并且作为奖励,为您提供触发的套接字列表。
asyncoro支持异步 TCP 和 UDP 套接字(以及许多其他功能)。与其他框架不同,使用 asyncoro 进行编程与使用线程非常相似。一个简单的 UDP 客户端/服务器程序来说明:
import socket, asyncoro
def server_proc(n, sock, coro=None):
for i in xrange(n):
msg, addr = yield sock.recvfrom(1024)
print('Received "%s" from %s:%s' % (msg, addr[0], addr[1]))
sock.close()
def client_proc(host, port, coro=None):
sock = asyncoro.AsynCoroSocket(socket.socket(socket.AF_INET, socket.SOCK_DGRAM))
msg = 'client socket: %s' % (sock.fileno())
yield sock.sendto(msg, (host, port))
sock.close()
if __name__ == '__main__':
sock = asyncoro.AsynCoroSocket(socket.socket(socket.AF_INET, socket.SOCK_DGRAM))
sock.bind(('127.0.0.1', 0))
host, port = sock.getsockname()
n = 100
server_coro = asyncoro.Coro(server_proc, n, sock)
for i in range(n):
asyncoro.Coro(client_proc, host, port)
asyncoro 尽可能使用有效的轮询机制。只有 Windows 和 UDP 套接字才使用低效的“选择”(但如果安装了pywin32 ,则对 TCP 使用高效的 Windows I/O 完成端口)。
我认为如果你坚持使用 tornado 的 ioloop 并想做 UDP 套接字处理,你应该使用 UDP 版本的 tornado IOStream。我在自己的项目中成功地做到了这一点。称它为 UDPStream 有点用词不当(因为它不是一个流),但基本的使用应该很容易集成到您的应用程序中。
参见代码: http: //kyle.graehl.org/coding/2012/12/07/tornado-udpstream.html