Select-based python chat room program and selectpython chat room Program
For details about python network programming, see python select network programming.
In python, the select function is an interface for direct access to the underlying operating system. It is used to monitor sockets, files, and pipes, Waiting for IO completion (Waiting for I/O completion ). When there are readable, writable, or abnormal events, select can be easily monitored. Select. select (rlist, wlist, xlist [, timeout]) transmits three parameters, a list of object Objects Observed for input, A list of file objects observed for output and a list of file objects observed for error exceptions. The fourth parameter is an optional parameter, indicating the time-out seconds. 3 tuple are returned, and each tuple is a list of prepared objects. It is in the same order as the parameters of the front edge.
The chat room program is as follows. When multiple clients are running, you can chat with each other and enter "exit" to exit.
Server code
#! /Bin/env python #-*-coding: utf8-*-"server select" "import sysimport timeimport socketimport selectimport loggingimport Queueg_select_timeout = 10 class Server (object ): def _ init _ (self, host = '10. 1.32.80', port = 33333, timeout = 2, client_nums = 10): self. _ host = host self. _ port = port self. _ timeout = timeout self. _ client_nums = client_nums self. _ buffer_size = 1024 self. server = socket. socket (soc Ket. AF_INET, socket. SOCK_STREAM) self. server. setblocking (False) self. server. settimeout (self. _ timeout) self. server. setsockopt (socket. SOL_SOCKET, socket. SO_KEEPALIVE, 1) # keepalive self. server. setsockopt (socket. SOL_SOCKET, socket. SO_REUSEADDR, 1) # port multiplexing server_host = (self. _ host, self. _ port) try: self. server. bind (server_host) self. server. listen (self. _ client_nums) handle T: raise self. inputs = [self. Server] # select received file descriptor list self. outputs = [] # output file descriptor list self. message_queues ={}# Message Queue self. client_info = {} def run (self): while True: readable, writable, predictional = select. select (self. inputs, self. outputs, self. inputs, g_select_timeout) if not (readable or writable or predictional): continue for s in readable: if s is self. server: # client connection, client_address = s. accept () # print "conne Ction ", connection print" % s connect. "% str (client_address) connection. setblocking (0) # non-blocking self. inputs. append (connection) # Add the client to inputs self. client_info [connection] = str (client_address) self. message_queues [connection] = Queue. queue () # One Message Queue (else) for each client: # client. data is sent to try: data = s. recv (self. _ buffer_size) handle T: err_msg = "Client Error! "Logging. error (err_msg) if data: # print data = "% s say: % s" % (time. strftime ("% Y-% m-% d % H: % M: % S"), self. client_info [s], data) self. message_queues [s]. put (data) # Add a message in the queue if s not in self. outputs: # message self. outputs. append (s) else: # Client disconnected # Interpret empty result as closed connection print "Client: % s Close. "% str (self. client_info [s]) if s in self. outputs: self. outputs. remove (s) self. inputs. Remove (s) s. close () del self. message_queues [s] del self. client_info [s] for s in writable: # When outputs has a message, try: next_msg = self. message_queues [s]. get_nowait () # obtain the Queue t Queue without blocking. empty: err_msg = "Output Queue is Empty! "# G_logFd.writeFormatMsg (g_logFd.LEVEL_INFO, err_msg) self. outputs. remove (s) failed t Exception, e: # when the client is closed, both writable and readable Data will be available, and the keyerror err_msg = "Send Data Error! ErrMsg: % s "% str (e) logging. error (err_msg) if s in self. outputs: self. outputs. remove (s) else: for cli in self. client_info: # send to other clients if cli is not s: try: cli. sendall (next_msg) failed t Exception, e: # If sending fails, turn off err_msg = "Send Data to % s Error! ErrMsg: % s "% (str (self. client_info [cli]), str (e) logging. error (err_msg) print "Client: % s Close Error. "% str (self. client_info [cli]) if cli in self. inputs: self. inputs. remove (cli) cli. close () if cli in self. outputs: self. outputs. remove (s) if cli in self. message_queues: del self. message_queues [s] del self. client_info [cli] for s in logging tional: logging. error ("Client: % s Close Error. "% str (self. client_info [cli]) if s in self. inputs: self. inputs. remove (s) s. close () if s in self. outputs: self. outputs. remove (s) if s in self. message_queues: del self. message_queues [s] del self. client_info [s] if "_ main _" = _ name __: Server (). run ()
Client code
#! /Usr/local/bin/python # *-* coding: UTF-8-*-"client. py "import sysimport timeimport socketimport threadingclass Client (object): def _ init _ (self, host, port = 33333, timeout = 1, reconnect = 2): self. _ host = host self. _ port = port self. _ timeout = timeout self. _ buffer_size = 1024 self. _ flag = 1 self. client = None self. _ lock = threading. lock () @ property def flag (self): return self. _ flag @ flag. set Ter def flag (self, new_num): self. _ flag = new_num def _ connect (self): client = socket. socket (socket. AF_INET, socket. SOCK_STREAM) # client. bind ('0. 0.0.0 ', 12345,) client. setblocking (True) client. settimeout (self. _ timeout) client. setsockopt (socket. SOL_SOCKET, socket. SO_REUSEADDR, 1) # port multiplexing server_host = (self. _ host, self. _ port) try: client. connect (server_host) handle T: raise return client def sen D_msg (self): if not self. client: return while True: time. sleep (0.1) # data = raw_input () data = sys. stdin. readline (). strip () if "exit" = data. lower (): with self. _ lock: self. flag = 0 break self. client. sendall (data) return def recv_msg (self): if not self. client: return while True: data = None with self. _ lock: if not self. flag: print 'byebye ~~ 'Break try: data = self. client. recv (self. _ buffer_size) blocks t socket. timeout: continue failed T: raise if data: print "% s \ n" % data time. sleep (0.1) return def run (self): self. client = self. _ connect () send_proc = threading. thread (target = self. send_msg) recv_proc = threading. thread (target = self. recv_msg) recv_proc.start () send_proc.start () recv_proc.join () send_proc.join () self. client. close () if "_ main _" = _ name __: Client ('10. 1.32.80 '). run ()