1+ import socket
2+ import select
3+
4+ # Constants
5+ MAX_CLIENTS = 1000
6+ SERVER_PORT = 7711
7+
8+ # Client class
9+ class Client :
10+ def __init__ (self , sock , addr ):
11+ self .socket = sock
12+ self .addr = addr
13+ self .nick = f"user:{ addr [1 ]} "
14+
15+ # Chat class
16+ class Chat :
17+ def __init__ (self ):
18+ self .clients = {}
19+ self .server_socket = socket .socket (socket .AF_INET , socket .SOCK_STREAM )
20+ self .server_socket .setsockopt (socket .SOL_SOCKET , socket .SO_REUSEADDR , 1 )
21+ self .server_socket .bind (("0.0.0.0" , SERVER_PORT ))
22+ self .server_socket .listen (511 )
23+ self .client_sockets = [self .server_socket ]
24+
25+ def add_client (self , client_socket , addr ):
26+ client = Client (client_socket , addr )
27+ self .clients [client_socket ] = client
28+ self .client_sockets .append (client_socket )
29+
30+ welcome_msg = "Welcome to Simple Chat! Use /nick <nick> to set your nick.\n "
31+ client_socket .send (welcome_msg .encode ())
32+ print (f"Connected client { addr [1 ]} " )
33+
34+ def remove_client (self , client_socket ):
35+ print (f"Disconnected client { self .clients [client_socket ].addr [1 ]} , nick={ self .clients [client_socket ].nick } " )
36+ del self .clients [client_socket ]
37+ self .client_sockets .remove (client_socket )
38+
39+ def run (self ):
40+ while True :
41+ rlist , _ , _ = select .select (self .client_sockets , [], [], 1 )
42+
43+ for ready_socket in rlist :
44+ if ready_socket == self .server_socket :
45+ client_socket , addr = self .server_socket .accept ()
46+ self .add_client (client_socket , addr )
47+ else :
48+ try :
49+ data = ready_socket .recv (256 )
50+ if not data :
51+ self .remove_client (ready_socket )
52+ else :
53+ client = self .clients [ready_socket ]
54+
55+ if data [0 ] == b"/" :
56+ args = data .decode ()[1 :].split (" " )
57+ cmd = args [0 ]
58+ if cmd == "nick" and len (args ) > 1 :
59+ client .nick = args [1 ]
60+ else :
61+ errmsg = "Unsupported command\n "
62+ ready_socket .send (errmsg .encode ())
63+
64+ else :
65+ msg = f"{ client .nick } > { data .decode ()} " .encode ()
66+ print (msg .decode (), end = "" )
67+
68+ for sock in self .clients :
69+ if sock != ready_socket :
70+ sock .send (msg )
71+
72+ except Exception as e :
73+ self .remove_client (ready_socket )
74+
75+ if __name__ == "__main__" :
76+ chat = Chat ()
77+ chat .run ()
0 commit comments