phy*_*cus 7 python asynchronous multiplayer websocket async-await
我正在尝试通过websockets在 Python 中构建多人游戏(准确地说是纸牌游戏),但目前我在早期步骤中失败了。
我正在尝试做的事情:
什么有效:
我尝试过的:
客户端.py
import asyncio
import websockets
import random
def random_name():
return "".join([random.choice("abcdefghijkl") for _ in range(5)])
async def main():
uri = "ws://localhost:1235"
print("Starting...")
async with websockets.connect(uri) as ws:
client_name = random_name()
await ws.send(client_name)
print(await ws.recv()) # server sends :client_name registered
print(await ws.recv()) # server sends: 3 people registered
print(await ws.recv()) # server sends: Waiting for input
inp = input()
await ws.send(inp)
asyncio.get_event_loop().run_until_complete(main())
Run Code Online (Sandbox Code Playgroud)
server.py (非常幼稚的方法)
import websockets
import asyncio
clients = []
async def main(ws, *args, **kwargs):
while True:
print(f"Waiting for new connection! {ws}")
client_name = await ws.recv()
clients.append((client_name, ws, ws.remote_address))
await ws.send(f"{client_name} registered on {ws.remote_address}")
if len(clients) >= 3:
registered_clients = ', '.join([c[0] for c in clients])
print(f"3 clients ({registered_clients}) registered")
break
for name, ws_, _ in clients:
await ws_.send(f"3 clients registered ({registered_clients})")
await ws_.send(f"Waiting for input")
for _ in clients:
inp = await ws_.recv()
print(ws_.remote_address, inp)
start_server = websockets.serve(main, "localhost", "1235")
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
Run Code Online (Sandbox Code Playgroud)
这失败了RuntimeError: cannot call recv while another coroutine is already waiting for the next message。看来我不能单独等待每个连接的客户端的答复。尽管并不完美,但我认为我可以通过查看远程地址来区分每个客户端。为此,我将 main 函数修改为
server.py,主要功能(简单方法)
async def main(ws, *args, **kwargs):
while True:
print(f"Waiting for new connection! {ws}")
client_name = await ws.recv()
clients.append((client_name, ws, ws.remote_address))
await ws.send(f"{client_name} registered on {ws.remote_address}")
if len(clients) >= 3:
registered_clients = ', '.join([c[0] for c in clients])
print(f"3 clients ({registered_clients}) registered")
break
for name, ws_ in clients:
await ws_.send(f"3 clients registered ({registered_clients})")
await ws_.send(f"Waiting for input")
for _ in range(len(clients)):
inp = await ws.recv()
print(ws.remote_address, inp)
Run Code Online (Sandbox Code Playgroud)
这也不起作用,因为循环不会中断所有连接的客户端。
我的问题:
websockets适合我的框架吗?有两件事让我想到:
websockets包,将有利于我更好地了解该asyncio模块。但如果有人说,我应该切换到aiohttp,等等flask-sockets。tornado我也愿意这样做。