Я пытаюсь создать серверное приложение, которое по существу управляет несколькими сокетами для данных, отправляемых по локальной сети.
Сначала я провел несколько тестов как на Linux, так и на Windows с их библиотеками (такими как Winsock), а также с библиотекой ASIO, но цель состоит в том, чтобы запустить ее в среде Linux.
Полное приложение будет чем-то, что открывает сокеты Н (возможно, многопоточность асинхронно) и по существу ничего не делает, пока каждый сокет не получит некоторые данные. Только в этот момент сервер будет анализировать пакеты и выполнять некоторые преобразования. Это связано с тем, что эти данные будут иметь другую структуру, и на основании этого было запрошено другое соединение (по крайней мере, это то, что меня просят сделать). Таким образом, в фиксированное время у меня будут доступны пакеты Н, которые затем будут «перекомпонованы» сервером.
По сути, каждый сокет несколько «привязан» к типу данных, который он должен получать.
Теперь проблема в том, что я не понимаю, какое решение реализовать для этого сценария, потому что я «вынужден» использовать протокол UDP, а также использовать разные сокеты. Насколько я знаю, для такого рода вещей используется протокол TCP, так что каждая пара сокетов может устанавливать соединение и выполнять свои собственные действия.
Более того, я не могу использовать один UDP-сокет для получения всего. Это в основном потому, что: A- Меня спрашивали по-другому; B- даже если синхронизация пакетов не будет реальной проблемой, я не смогу получить их все в перемешанном виде, потому что потребуется отправка дополнительной информации от клиентов (на которую я не могу повлиять).
На самом деле теперь я понимаю, почему не так много документации о сценариях UDP. Я бы с удовольствием перешел на TCP, чтобы хотя бы приблизительно представлять, что делать, но пока не могу.
Можете ли вы помочь мне лучше понять ситуацию?
Как было сказано в комментариях, вы можете контролировать несколько портов с помощью функции select
. Он принимает списки портов для проверки на чтение, запись или наличие ошибок и возвращает списки портов в запрошенном состоянии.
Ниже приведен пример просмотра 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!