|
5 | 5 |
|
6 | 6 | # `pip install websockets` |
7 | 7 | import websockets |
| 8 | + |
8 | 9 | # The websockets docs are also the source for this code. |
9 | 10 | # See https://websockets.readthedocs.io/en/stable/howto/quickstart.html#manage-application-state. |
10 | 11 | # I modified the code slightly, to also let the server indepently send messages to the clients, to denote the full duplex nature of Websockets. |
11 | 12 |
|
12 | 13 | USERS = set() |
13 | 14 | COUNTER = 0 |
14 | 15 |
|
| 16 | + |
15 | 17 | async def broadcast(users, data, desc): |
16 | | - if users: |
17 | | - await asyncio.wait([ |
18 | | - asyncio.create_task( |
19 | | - send(user, data, desc) |
20 | | - ) for user in users |
21 | | - ]) |
| 18 | + if users: |
| 19 | + await asyncio.wait( |
| 20 | + [asyncio.create_task(send(user, data, desc)) for user in users] |
| 21 | + ) |
| 22 | + |
22 | 23 |
|
23 | 24 | async def send(user, data, desc): |
24 | | - await user.send(json.dumps({ |
25 | | - "data": data, |
26 | | - "desc": desc |
27 | | - })) |
| 25 | + await user.send(json.dumps({"data": data, "desc": desc})) |
| 26 | + |
28 | 27 |
|
29 | 28 | async def server_messages(): |
30 | | - # This is the place where we do serverside stuff and send messages to the connected clients, if needed. |
31 | | - global COUNTER |
32 | | - while True: |
33 | | - await asyncio.sleep(2) |
34 | | - COUNTER += 1 |
35 | | - await broadcast(USERS, COUNTER, "counter") |
| 29 | + # This is the place where we do serverside stuff and send messages to the connected clients, if needed. |
| 30 | + global COUNTER |
| 31 | + while True: |
| 32 | + await asyncio.sleep(2) |
| 33 | + COUNTER += 1 |
| 34 | + await broadcast(USERS, COUNTER, "counter") |
| 35 | + |
36 | 36 |
|
37 | 37 | def user_messages(): |
38 | | - return websockets.serve(handle_connection, "localhost", PORT) |
| 38 | + return websockets.serve(handle_connection, "localhost", PORT) |
| 39 | + |
39 | 40 |
|
40 | 41 | def parse(message): |
41 | | - info = json.loads(message) |
42 | | - return info["data"], info["desc"] |
| 42 | + info = json.loads(message) |
| 43 | + return info["data"], info["desc"] |
| 44 | + |
43 | 45 |
|
44 | 46 | async def handle_connection(user): |
45 | | - global USERS, COUNTER |
46 | | - try: |
47 | | - USERS.add(user) |
48 | | - await broadcast(USERS, len(USERS), "amount_users") |
49 | | - await send(user, COUNTER, "counter") |
50 | | - async for message in user: |
51 | | - # this is the place where we handle messages sent by a connected client. This is done indepently for each client. |
52 | | - data, desc = parse(message) |
53 | | - match desc: |
54 | | - case "update_counter": |
55 | | - COUNTER = COUNTER + data |
56 | | - await broadcast(USERS, COUNTER, "counter") |
57 | | - case other: |
58 | | - print(f"unsupported: \"{desc}\": {data}") |
59 | | - finally: |
60 | | - USERS.remove(user) |
61 | | - await broadcast(USERS, len(USERS), "amount_users") |
| 47 | + global USERS, COUNTER |
| 48 | + try: |
| 49 | + USERS.add(user) |
| 50 | + await broadcast(USERS, len(USERS), "amount_users") |
| 51 | + await send(user, COUNTER, "counter") |
| 52 | + async for message in user: |
| 53 | + # this is the place where we handle messages sent by a connected client. This is done indepently for each client. |
| 54 | + data, desc = parse(message) |
| 55 | + match desc: |
| 56 | + case "update_counter": |
| 57 | + COUNTER = COUNTER + data |
| 58 | + await broadcast(USERS, COUNTER, "counter") |
| 59 | + case other: |
| 60 | + print(f'unsupported: "{desc}": {data}') |
| 61 | + finally: |
| 62 | + USERS.remove(user) |
| 63 | + await broadcast(USERS, len(USERS), "amount_users") |
| 64 | + |
62 | 65 |
|
63 | 66 | PORT = 6789 |
64 | 67 |
|
| 68 | + |
65 | 69 | async def main(): |
66 | | - await asyncio.gather( |
67 | | - server_messages(), |
68 | | - user_messages() |
69 | | - ) |
| 70 | + await asyncio.gather(server_messages(), user_messages()) |
| 71 | + |
70 | 72 |
|
71 | 73 | if __name__ == "__main__": |
72 | | - print(f'Listening on ws://localhost:{PORT}/') |
73 | | - try: |
74 | | - asyncio.run(main()) |
75 | | - except KeyboardInterrupt: |
76 | | - print("\nbye") |
| 74 | + print(f"Listening on ws://localhost:{PORT}/") |
| 75 | + try: |
| 76 | + asyncio.run(main()) |
| 77 | + except KeyboardInterrupt: |
| 78 | + print("\nbye") |
0 commit comments