具有多个套接字的 UDP 网络
UDP Networking with multiple sockets
我正在尝试创建一个服务器应用程序,该应用程序基本上控制通过本地网络发送的数据的多个套接字。
我首先在 linux 和 windows 上用它们的库(例如 Winsock)和 ASIO 库做了一些测试,但目标是让它 运行 在 linux 环境中。
完整的应用程序将打开 N 套接字(可能是异步多线程)并且在每个套接字收到一些之前基本上什么都不做数据。只有在那个时候,服务器才会分析数据包并进行一些转换。这是因为这些数据将具有不同的结构,并且基于此请求了不同的连接(这至少是我被要求做的)。
所以在固定的时间,我会有 N 个数据包可用,然后服务器将“重新组合”这些数据包。
本质上,每个套接字都在某种程度上“绑定”到它应该接收的数据类型。
现在的问题是,我不明白要为这种情况实施哪种解决方案,因为我“被迫”使用 UDP 协议,以及使用不同的套接字。
据我所知,对于这种东西,使用的是 TCP 协议,这样每个套接字对都可以建立连接并做自己的事情。
此外,我无法使用单个 UDP 套接字来接收所有内容。这主要是因为:
A- 我被问到不同的问题; B-即使数据包的时间不是真正的问题,我也无法将它们全部混合在一起,因为它需要从客户端发送额外的信息(我无法控制)。
事实上,现在我明白了为什么没有那么多关于 UDP 场景的文档。我很乐意切换到 TCP,这样至少我可以大致了解该怎么做,但目前我做不到。
你能帮我更好地了解情况吗?
正如评论所建议的那样,您可以使用 select
功能监视多个端口。它需要端口列表来检查可读性、可写性或错误,以及 returns 个处于请求状态的端口列表。
下面是一个监视 5 个端口以提高可读性的示例,并在所有 5 个端口都收到一些东西时退出:
import socket
import select
N = 5
base_port = 5000
# Create N sockets and bind to ports 5000 to 5000+N-1:
socks = [socket.socket(type=socket.SOCK_DGRAM) for _ in range(N)]
for i,s in enumerate(socks):
s.bind(('',base_port+i))
# Flags to track that something was received on a particular port
got = [False] * N
while not all(got):
# Watch all N sockets for readability only
readable,writable,errors = select.select(socks,[],[])
# Only a socket that has something to read will be in "readable"
for s in readable:
port = s.getsockname()[1] # which port was it
data,addr = s.recvfrom(4096)
print(f'From {port}: {data}')
got[port-5000] = True
print("Got'em all!")
演示(客户端)
>>> from socket import *
>>> s=socket(type=SOCK_DGRAM)
>>> s.sendto(b'abc',('localhost',5001))
3
>>> s.sendto(b'abc',('localhost',5002))
3
>>> s.sendto(b'abc',('localhost',5003))
3
>>> s.sendto(b'abc',('localhost',5004))
3
>>> s.sendto(b'abc',('localhost',5000))
3
演示(服务器)
From 5001: b'abc'
From 5002: b'abc'
From 5003: b'abc'
From 5004: b'abc'
From 5000: b'abc'
Got'em all!
我正在尝试创建一个服务器应用程序,该应用程序基本上控制通过本地网络发送的数据的多个套接字。
我首先在 linux 和 windows 上用它们的库(例如 Winsock)和 ASIO 库做了一些测试,但目标是让它 运行 在 linux 环境中。
完整的应用程序将打开 N 套接字(可能是异步多线程)并且在每个套接字收到一些之前基本上什么都不做数据。只有在那个时候,服务器才会分析数据包并进行一些转换。这是因为这些数据将具有不同的结构,并且基于此请求了不同的连接(这至少是我被要求做的)。 所以在固定的时间,我会有 N 个数据包可用,然后服务器将“重新组合”这些数据包。
本质上,每个套接字都在某种程度上“绑定”到它应该接收的数据类型。
现在的问题是,我不明白要为这种情况实施哪种解决方案,因为我“被迫”使用 UDP 协议,以及使用不同的套接字。 据我所知,对于这种东西,使用的是 TCP 协议,这样每个套接字对都可以建立连接并做自己的事情。
此外,我无法使用单个 UDP 套接字来接收所有内容。这主要是因为: A- 我被问到不同的问题; B-即使数据包的时间不是真正的问题,我也无法将它们全部混合在一起,因为它需要从客户端发送额外的信息(我无法控制)。
事实上,现在我明白了为什么没有那么多关于 UDP 场景的文档。我很乐意切换到 TCP,这样至少我可以大致了解该怎么做,但目前我做不到。
你能帮我更好地了解情况吗?
正如评论所建议的那样,您可以使用 select
功能监视多个端口。它需要端口列表来检查可读性、可写性或错误,以及 returns 个处于请求状态的端口列表。
下面是一个监视 5 个端口以提高可读性的示例,并在所有 5 个端口都收到一些东西时退出:
import socket
import select
N = 5
base_port = 5000
# Create N sockets and bind to ports 5000 to 5000+N-1:
socks = [socket.socket(type=socket.SOCK_DGRAM) for _ in range(N)]
for i,s in enumerate(socks):
s.bind(('',base_port+i))
# Flags to track that something was received on a particular port
got = [False] * N
while not all(got):
# Watch all N sockets for readability only
readable,writable,errors = select.select(socks,[],[])
# Only a socket that has something to read will be in "readable"
for s in readable:
port = s.getsockname()[1] # which port was it
data,addr = s.recvfrom(4096)
print(f'From {port}: {data}')
got[port-5000] = True
print("Got'em all!")
演示(客户端)
>>> from socket import *
>>> s=socket(type=SOCK_DGRAM)
>>> s.sendto(b'abc',('localhost',5001))
3
>>> s.sendto(b'abc',('localhost',5002))
3
>>> s.sendto(b'abc',('localhost',5003))
3
>>> s.sendto(b'abc',('localhost',5004))
3
>>> s.sendto(b'abc',('localhost',5000))
3
演示(服务器)
From 5001: b'abc'
From 5002: b'abc'
From 5003: b'abc'
From 5004: b'abc'
From 5000: b'abc'
Got'em all!