Python编程之基础知识练习_007
Posted orcsir
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python编程之基础知识练习_007相关的知识,希望对你有一定的参考价值。
练习内容:socket,IO多路复用,Python selectors库,实现简单的群聊。
1.服务端代码
1 __author__ = ‘Orcsir‘ 2 import selectors 3 import threading 4 import socket 5 from collections import namedtuple 6 7 8 class ChatServer: 9 def __init__(self, ip="0.0.0.0", port=9527): 10 self.addr = (ip, port) 11 self.sock = socket.socket() 12 self.selector = selectors.DefaultSelector() 13 self.data = namedtuple("data", ["callback", "datagram"]) 14 15 def start(self): 16 self.sock.bind(self.addr) 17 self.sock.listen() 18 self.sock.setblocking(False) 19 self.selector.register(self.sock, selectors.EVENT_READ, self.data(self.accept, b"")) 20 threading.Thread(target=self.select, name="select").start() 21 22 def select(self): 23 while True: 24 try: 25 events = self.selector.select() 26 except: 27 self.stop() 28 return 29 30 for key, mask in events: 31 data = key.data 32 callback = data.callback 33 datagram = data.datagram 34 callback(key.fileobj, mask, datagram) 35 36 def accept(self, sock: socket.socket, mask, data): 37 conn, raddr = sock.accept() 38 conn.setblocking(False) 39 self.selector.register(conn, selectors.EVENT_READ | selectors.EVENT_WRITE, self.data(self.recv_send, data)) 40 41 # 处理数据接收 42 def _process_recv(self, conn: socket.socket, mask): 43 try: 44 data = conn.recv(1024) 45 except: 46 self.selector.unregister(conn) 47 conn.close() 48 return 49 50 if data: 51 for key in self.selector.get_map().values(): 52 if key.fileobj != self.sock: 53 datagram = "From {}. Contents: {}".format(conn.getpeername(), data.decode()).encode() 54 self.selector.modify(key.fileobj, selectors.EVENT_WRITE, self.data(self.recv_send, datagram)) 55 else: 56 self.selector.unregister(conn) 57 conn.close() 58 59 # 处理数据发送 60 def _process_send(self, conn: socket.socket, mask, datagram: bytes): 61 conn.send(datagram) 62 self.selector.modify(conn, selectors.EVENT_READ, self.data(self.recv_send, b"")) 63 64 # 分发函数 65 def recv_send(self, conn: socket.socket, mask, datagram: bytes): 66 if mask & selectors.EVENT_READ: 67 self._process_recv(conn, mask) 68 elif mask & selectors.EVENT_WRITE: 69 self._process_send(conn, mask, datagram) 70 71 def stop(self): 72 connects = [] 73 if self.selector.get_map(): 74 for key in self.selector.get_map().values(): 75 connects.append(key.fileobj) 76 77 for conn in connects: 78 self.selector.unregister(conn) 79 conn.close() 80 self.selector.close() 81 82 83 if __name__ == ‘__main__‘: 84 cs = ChatServer() 85 cs.start() 86 while True: 87 cmd = input(">>>") 88 if cmd.strip() == "quit": 89 cs.stop() 90 break
2.客户端代码
1 __author__ = ‘Orcsir‘ 2 3 import socket 4 import threading 5 import logging 6 7 FORMAT = "%(message)s" 8 logging.basicConfig(format=FORMAT, level=logging.INFO) 9 10 11 class ChatClient: 12 def __init__(self, ip="127.0.0.1", port=9527): 13 self.sock = socket.socket() 14 self.raddr = (ip, port) 15 16 def start(self): 17 self.sock.connect(self.raddr) 18 threading.Thread(target=self._recv, name="recv").start() 19 20 def _recv(self): 21 while True: 22 try: 23 data = self.sock.recv(1024) 24 except: 25 self.sock.close() 26 return 27 if data: 28 logging.info("recv: {}".format(data.decode())) 29 else: 30 self.sock.close() 31 return 32 33 def send(self, data: str): 34 self.sock.send(data.encode()) 35 36 def stop(self): 37 if self.sock: 38 self.sock.close() 39 40 41 def main(): 42 cc = ChatClient() 43 cc.start() 44 while True: 45 cmd = input(">>>") 46 if cmd.strip() == "quit": 47 cc.stop() 48 return 49 cc.send(cmd) 50 51 main()
3.启动两个ipython模拟客户端
以上是关于Python编程之基础知识练习_007的主要内容,如果未能解决你的问题,请参考以下文章