Python3基础-selectors模块
官方文档见:https://docs.python.org/3/library/selectors.html
selectors模块 它封装了IO多路复用中的select和epoll,能够更快,更方便的实现多并发效果。
1. 模块定义了一个 BaseSelector的抽象基类, 以及它的子类,包括:SelectSelector, PollSelector, EpollSelector, DevpollSelector, KqueueSelector.
另外还有一个DefaultSelector类,它其实是以上其中一个子类的别名而已,它自动选择为当前环境中最有效的Selector,所以平时用 DefaultSelector类就可以了,其它用不着。
2. 模块定义了两个常量,用于描述 event Mask
EVENT_READ : 表示可读的; 它的值其实是1;
EVENT_WRITE: 表示可写的; 它的值其实是2;
3. 模块定义了一个 SelectorKey类, 一般用这个类的实例 来描述一个已经注册的文件对象的状态, 这个类的几个属性常用到:
fileobj: 表示已经注册的文件对象;
fd: 表示文件对象的描述符,是一个整数,它是文件对象的 fileno()方法的返回值;
events: 表示注册一个文件对象时,我们等待的events, 即上面的event Mask, 是可读还是可写呢!!
data: 表示注册一个文件对象是邦定的data;
register(fileobj, events, data=None) 作用:注册一个文件对象。
参数: fileobj——即可以是fd 也可以是一个拥有fileno()方法的对象;
events——上面的event Mask 常量; data
返回值: 一个SelectorKey类的实例;
unregister(fileobj) 作用: 注销一个已经注册过的文件对象;
返回值:一个SelectorKey类的实例;
modify(fileobj, events, data=None) 作用:用于修改一个注册过的文件对象,比如从监听可读变为监听可写;它其实就是register() 后再跟unregister(), 但是使用modify( ) 更高效;
返回值:一个SelectorKey类的实例;
select(timeout=None) 作用: 用于选择满足我们监听的event的文件对象;
返回值: 是一个(key, events)的元组, 其中key是一个SelectorKey类的实例, 而events 就是 event Mask(EVENT_READ或EVENT_WRITE,或者二者的组合)
close() 作用:关闭 selector。 最后一定要记得调用它, 要确保所有的资源被释放;
get_key(fileobj) 作用: 返回注册文件对象的 key;
返回值 :一个SelectorKey类的实例;
实例:
server.py
1 import selectors 2 import socket 3 4 # selectors模块默认会用epoll,如果你的系统中没有epoll(比如windows)则会自动使用select 5 sel = selectors.DefaultSelector() # 生成一个select对象 6 7 8 def accept(sock, mask): 9 conn, addr = sock.accept() # Should be ready 10 print('accepted', conn, 'from', addr) 11 conn.setblocking(False) # 设定非阻塞 12 sel.register(conn, selectors.EVENT_READ, read) # 新连接注册read回调函数 13 14 15 def read(conn, mask): 16 try: 17 data = conn.recv(1024) # Should be ready 18 if not data: 19 raise Exception 20 print(str(data.decode("utf-8"))) 21 conn.send(data) 22 except Exception as e: 23 print('closing', conn) 24 sel.unregister(conn) 25 conn.close() 26 27 sock = socket.socket() 28 sock.bind(('127.0.0.1', 8899)) 29 sock.listen() 30 sock.setblocking(False) 31 sel.register(sock, selectors.EVENT_READ, accept) # 把刚生成的sock连接对象注册到select连接列表中,并交给accept函数处理 32 33 while True: 34 print("server-------") 35 events = sel.select() # 默认是阻塞,有活动连接就返回活动的连接列表 36 # 这里看起来是select,其实有可能会使用epoll,如果你的系统支持epoll,那么默认就是epoll 37 # print("event==",events) 38 for key, mask in events: 39 # print("key==",key) 40 # print("mask==",mask) 41 callback = key.data # 去调accept函数 42 # print("callback==",callback) 43 callback(key.fileobj, mask) # key.fileobj就是readable中的一个socket连接对象
client.py
1 import socket 2 3 sk = socket.socket() 4 sk.connect(("127.0.0.1", 8899)) 5 6 while True: 7 inp = input(">>>:") 8 sk.send(inp.encode("utf-8")) # 发送信息 9 data = sk.recv(1024) # 接受信息 10 print(data.decode("utf-8")) # 打印出来client2.py
浙公网安备 33010602011771号