demand analysis
1 can be connected to a plurality of clients;
2. The client does not respond for a long time can be turned off to save resources;
3. capable of sending, a message sent by a user, all clients may receive;
Thinking
Directly socket.socket class can be achieved, but then we need to listen to manually write, write, accept, accept put into a separate thread, each with a thread into a new open thread.
Here we use socketserver this library to implement, so we just need to write out a key step, the other can help us complete automation.
. 1 Mport SocketServer 2 Import datetime . 3 Import Threading . 4 . 5 . 6 class myHandle (of SocketServer.BaseRequestHandler): # Each instance of a thread . 7 DEF self_server_init (Self): . 8 IF Not the hasattr (self.server, " Clients " ): . 9 setattr (self.server, " Clients " , {}) # If you do not have this property gave him an additional 10 IF not hasattr (self.server, " _lock_clients " ): 11 setattr(self.server, "lock_clients", threading.Lock()) 12 self.server.__dict__["hb_interval"] = 10 13 self.server.clients[self.key] = datetime.datetime.now().timestamp() # 记录时间 14 15 def setup(self): 16 # self init 17 self.event = threading.Event() 18 self.key = self.request, self.event 19 # self.server init 20 self.self_server_init() 21 22 def handle(self): 23 no_hb = set() 24 while not self.event.is_set(): 25 data = self.request.recv(1024) 26 print(data.decode()) 27 if data == b"^hb^": # 收到了心跳包 28 with self.server.lock_clients: 29 self.server.clients[self.key] = datetime.datetime.now().timestamp() 30 if data == b"" or data.strip() == b"quit " : 31 with self.server.lock_clients: 32 self.server.clients.pop (self.key, None) # If you exit to pop up 33 BREAK # because a thread is a connection 34 35 # If you do not quit we refresh time, there may be a new connection 36 self.server.clients [self.key] = datetime.datetime.now () timestamp (). 37 [ 38 is # sending messages, checking whether a time-out 39 with self.server.lock_clients: 40 for Key, T in self.server.clients.items (): 41 is IFdatetime.datetime.now () timestamp () - T> self.server.hb_interval:. # If a timeout at the recording Key 42 is no_hb.add (Key) # S and e can hash 43 is Continue 44 is Key [0] .send ( " from {}: {} " . .format (self.client_address, data.decode ()) encode ()) 45 for Key in no_hb: 46 is self.server.clients.pop (Key) # removed without heartbeat client 47 no_hb.clear () 48 49 DEF Finish (Self): 50 Super () Finish (). 51 is self.event.set() 52 53 54 server = socketserver.ThreadingTCPServer(("127.0.0.1", 9999), MyHandle) 55 server.serve_forever() # 启动