我认为我的问题非常容易和愚蠢,但我阅读了很多材料,无法想象如何做我想做的事。
所以,我使用websockets
库,我有这个algorythm:
# 1. get connection and start handle it
async def main_request_handler(ws, path):
proxy = Proxy()
try:
await proxy.start(ws, path)
2。在内部开始我创建第二个websocket来传递来自ws
的请求并接收答案以将它们发送到ws
while True:
request_raw = await self.ws_server.recv()
await self.process_request_from_server(request_raw)
问题是,我需要使用一个websocket服务器连接进行乘法运算
ws
个客户,我需要从ws_server
向每个人传达相同的答案。现在我只得到一个响应,因为.recv()只返回一个'订阅者的值。
如何解决这个问题?请注意,我使用while True
和async
答案 0 :(得分:2)
这是一个非常简单的pub / sub websockets服务器示例
import asyncio
import websockets
connections = set()
n = 0
async def handler(websocket, path):
global n
if path == "/sub":
n = n + 1
i = n
connections.add(websocket)
print("adding subscriber #", i)
try:
async for msg in websocket:
pass # ignore
except websockets.ConnectionClosed:
pass
finally:
print("removing subscriber #", i)
connections.remove(websocket)
elif path == "/pub":
async for msg in websocket:
print("<", msg)
for ws in connections:
asyncio.ensure_future(ws.send(msg))
start_server = websockets.serve(handler, 'localhost', 8765)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
一个示例订户客户端(运行其中一些):
import asyncio
import websockets
async def listen():
async with websockets.connect('ws://localhost:8765/sub') as websocket:
while True:
greeting = await websocket.recv()
print("< {}".format(greeting))
asyncio.get_event_loop().run_until_complete(listen())
和出版商:
import asyncio
import websockets
async def say():
async with websockets.connect('ws://localhost:8765/pub') as websocket:
while True:
msg = input("Enter message:")
if not msg:
break
await websocket.send(msg)
asyncio.get_event_loop().run_until_complete(say())
答案 1 :(得分:1)
换句话说,我需要在同一个循环中运行
.recv
并与多个使用者一起运行。在RxPy中我只能stream.emit(recv_result)
并使用像thatstrem.subscribe(callback_fn)
这样的项目,但这是回调方式,我需要异步
您的subscribe
方法可以接受协程功能,即使用async def
创建的功能。一旦发出某些内容,就可以实例化它们,并使用create_task
生成它们的协同程序:
def __init__(self, ...):
self._subscribers = []
def subsribe(self, corofn):
self._subscribers.append(corofn)
def emit(self, obj):
loop = asyncio.get_event_loop()
for corofn in self._subscribers:
coro = corofn(obj)
loop.create_task(coro)
async def main(self):
while True:
request_raw = await self.ws_server.recv()
self.emit(request_raw)
答案 2 :(得分:0)
我不确定我是否理解正确,但不是gathering多个协同程序是你想要的吗?
while True:
request_raw = await self.ws_server.recv()
# process by multiple clients parallely:
await asyncio.gather(
self.process_by_client_1(request_raw),
self.process_by_client_2(request_raw),
self.process_by_client_3(request_raw),
)
答案 3 :(得分:0)
感谢您的建议,他们可能会工作。我是通过队列完成的。
class SWebsocket(object):
def __init__(self, websocket: WebSocketServerProtocol):
self.ws = websocket
self.queues = {}
self.subscribe()
def subscribe(self):
# fire and forget function
asyncio.ensure_future(self.recv_mess())
async def recv_mess(self):
while True:
try:
data = await self.ws.recv()
except websockets.ConnectionClosed as e:
for _, q in self.queues.items():
await q.put(e)
return
for _, q in self.queues.items():
await q.put(data)
async def recv(self, id):
# read value from queue
if id not in self.queues:
self.queues[id] = asyncio.Queue()
data = await self.queues[id].get()
if isinstance(data, websockets.ConnectionClosed):
raise data
return data