-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathchat_server.py
More file actions
120 lines (79 loc) · 3.29 KB
/
chat_server.py
File metadata and controls
120 lines (79 loc) · 3.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import asyncio
from textwrap import dedent
class ConnectionPool:
def __init__(self):
self.connection_pool = set()
def send_welcome_message(self, writer):
message = dedent(f"""
===
(Welcome {writer.nickname}!
there are {len(self.connection_pool) - 1}users(s)
here besid you
Help:
- Type anything to chat
- /list will list all the connected users
- /quit will disconnect you
===
""")
writer.write(f"{message}\n".encode())
def broadcast(self, writer, message):
for user in self.connection_pool:
if user != writer:
#We dont need to also broadcast to theuser sending the message
user.write(f"{message}\n".encode())
def brodcast_user_join(self, writer):
self.broadcast(writer, f"{writer.nickname} just joined")
def broadcast_user_quit(self,writer):
self.broadcast(writer, f"{writer.nickname} just quit")
def broadcast_new_message(self, writer, message):
self.broadcast(writer, f"[{writer.nickname}] {message}")
def list_users(self, writer):
message = "===\n"
message += "Currently connection users"
for user in self.connection_pool:
if user == writer:
message += f"\n - {user.nickname} (you)"
else:
message += f"\n - {user.nickname}"
message += "\n==="
writer.write(f"{message}\n".encode())
def add_new_user_to_pool(self, writer):
self.connection_pool.add(writer)
def remove_user_from_pool(self, writer):
self.connection_pool.remove(writer)
async def handle_connection(reader, writer):
#Get a nickname for the new client
writer.write("> Choose your nickname: ".encode())
response = await reader.readuntil(b"\n")
writer.nickname = response.decode().strip()
connection_pool.add_new_user_to_pool(writer)
connection_pool.send_welcome_message(writer)
#Announce the arrival of this new useer
connection_pool.brodcast_user_join(writer)
while True:
try:
data = await reader.readuntil(b"\n")
except asyncio.exceptions.IncompleteReadError:
connection_pool.broadcast_user_quit(writer)
break
message = data.decode().strip()
if message == "/quit":
connection_pool.broadcast_user_quit(writer)
break
elif message == "/list":
connection_pool.list_users(writer)
else:
connection_pool.broadcast_new_message(writer, message)
await writer.drain()
if writer.is_closing():
break
#We're now outside the message loop, and the user has quit. Let's clean up...add()
writer.close()
await writer.wait_closed()
connection_pool.remove_user_from_pool(writer)
async def main():
server = await asyncio.start_server(handle_connection, "0.0.0.0", 5555)
async with server:
await server.serve_forever()
connection_pool = ConnectionPool()
asyncio.run(main())