| #!/usr/bin/env python |
| |
| # WS server example that synchronizes state across clients |
| |
| import asyncio |
| import json |
| import logging |
| import websockets |
| |
| logging.basicConfig() |
| |
| STATE = {"value": 0} |
| |
| USERS = set() |
| |
| |
| def state_event(): |
| return json.dumps({"type": "state", **STATE}) |
| |
| |
| def users_event(): |
| return json.dumps({"type": "users", "count": len(USERS)}) |
| |
| |
| async def notify_state(): |
| if USERS: # asyncio.wait doesn't accept an empty list |
| message = state_event() |
| await asyncio.wait([user.send(message) for user in USERS]) |
| |
| |
| async def notify_users(): |
| if USERS: # asyncio.wait doesn't accept an empty list |
| message = users_event() |
| await asyncio.wait([user.send(message) for user in USERS]) |
| |
| |
| async def register(websocket): |
| USERS.add(websocket) |
| await notify_users() |
| |
| |
| async def unregister(websocket): |
| USERS.remove(websocket) |
| await notify_users() |
| |
| |
| async def counter(websocket, path): |
| # register(websocket) sends user_event() to websocket |
| await register(websocket) |
| try: |
| await websocket.send(state_event()) |
| async for message in websocket: |
| data = json.loads(message) |
| if data["action"] == "minus": |
| STATE["value"] -= 1 |
| await notify_state() |
| elif data["action"] == "plus": |
| STATE["value"] += 1 |
| await notify_state() |
| else: |
| logging.error("unsupported event: {}", data) |
| finally: |
| await unregister(websocket) |
| |
| |
| start_server = websockets.serve(counter, "localhost", 6789) |
| |
| asyncio.get_event_loop().run_until_complete(start_server) |
| asyncio.get_event_loop().run_forever() |