# Filename: ChatRoomServer. py Import threading Import datetime Import socket # A simple log function Def log (lg ): Print (lg) # Chat room server listen thread class, this class is used for listening client login # When a client request to connect server, this class will start a connect thread Class ServerListenThread (threading. Thread ): Def _ init _ (self, hostname, port, accept ): Threading. Thread. _ init _ (self) Self. hostname = hostname Self. port = port Self. accept = accept Self. sock = socket. socket (socket. AF_INET, socket. SOCK_STREAM) Self. sock. setsockopt (socket. SOL_SOCKET, socket. SO_REUSEADDR, 1) Self. sock. bind (hostname, port )) Self. sock. listen (0) Log ('serverip: % s ServerPort: % s waiting for client... '% self. sock. getsockname ()) Def run (self ): Clientid = 1 While True: Client, cltadd = self. sock. accept () Log ('A request from Id = % s % s' % ('% d Address:' % clientid, cltadd )) If self. accept (clientid, client ): Clientid = clientid + 1 # Connect thread class, this class is used for connecting with client and signing client's message Class ServerConnectThread (threading. Thread ): Def _ init _ (self, clientid, client, encoding, receive, disconnect ): Threading. Thread. _ init _ (self) Self. client = client Self. clientid = clientid Self. encoding = encoding Self. receive = receive Self. disconnect = disconnect Self. clientname = None Self. inputs = self. client. makefile ('rb', 0) Self. outputs = self. client. makefile ('wb ', 0) Def run (self ): Self. sendstring ('input your name :') While True: String = self. readline () If string: String = string. lstrip () If len (string)> 0: Self. receive (self, string) Else: Self. inputs. close () Self. outputs. close () Break If self. clientname: Self. disconnect (self) Def sendstring (self, string ): Self. sendbytes (bytes (string, self. encoding )) Def sendbytes (self, bts ): Self. outputs. write (bts) Def readline (self ): Rec = self. inputs. readline () If rec: String = bytes. decode (rec, self. encoding) If len (string)> 2: String = string [0:-2] Else: String ='' Else: String = False Return string # Chat room server class, this class is constitute of a listen thread and other connect thread Class ChatRoomServer: Def _ init _ (self, ip = '0. 0.0.0 ', port = 9113, encoding = 'utf-8 '): Self. hostname = ip Self. encoding = encoding Self. port = port Self. clients = {} Self. clientnames = {} Def whenconnect (self, clientid, client ): Log ('a connect with Id = % s % s' % ('% d Address:' % clientid, client. getpeername ())) Connect = ServerConnectThread (clientid, client, self. encoding, self. whenreceive, self. whenexit) Connect. start () Return True Def whenreceive (self, client, string ): Log ('frome % d, receive: % s (% d) '% (client. clientid, string, len (string ))) If client. clientname: If string [0] = '.': Self. handlecmd (client, string [1:]) Else: Now = datetime. datetime. now () Sendstring = '% s \ r \ n % s \ r \ n' % (now, client. clientname, string) Self. sendtoall (sendstring, client) Else: If self. clientnames. _ contains _ (string ): Client. sendstring ('% s is exited !!! \ R \ n' % string) Else: Client. clientname = string Client. sendstring ('Hell, % s !!! \ R \ n' % client. clientname) Self. addclient (client) Return True Def whenexit (self, client ): Self. delclient (client) Return True Def handlecmd (self, client, cmd ): Log ('cmd: % s' % cmd) If cmd = 'user ': Client. sendstring ('user list (% d): \ r \ n' % len (self. clients )) For I in self. clients: Clt = self. clients [I] Client. sendstring ('% d \ t % s \ r \ n' % (clt. clientid, clt. clientname )) Else: Client. sendstring ('unknow command: % s: \ r \ n' % cmd) Def start (self ): Serverlisten = ServerListenThread (self. hostname, self. port, self. whenconnect) Serverlisten. start () Def sendtoall (self, string, notfor ): Sends = bytes (string, self. encoding) For I in self. clients: If not (notfor and notfor. clientid = I ): Self. clients [I]. sendbytes (sends) Def addclient (self, client ): Self. sendtoall ('% s logined !!! \ R \ n' % client. clientname, client) Self. clients [client. clientid] = client Self. clientnames [client. clientname] = client. clientid Def delclient (self, client ): Self. sendtoall ('% s logouted !!! \ R \ n' % client. clientname, client) Del self. clients [client. clientid] Del self. clientnames [client. clientname] # Start a chat room server ChatRoomServer (). start () |