大家好,又见面了,我是全栈君
在之前的博客中已经总结过分别在windows和linux操作系统下实现socket高并发(I/O异步)的方法,可以参考基于epoll的TP传输层实现和Windows之IOCP
下面对Python中实现socket高并发的selectors库进行总结,官方参考文档:https://docs.python.org/3/library/selectors.html
1. 示例代码
代码语言:javascript复制import selectors
import socket
sel = selectors.DefaultSelector()
def accept(sock, mask):
conn, addr = sock.accept() # Should be ready
print('accepted', conn, 'from', addr)
conn.setblocking(False)
sel.register(conn, selectors.EVENT_READ, read)
def read(conn, mask):
data = conn.recv(1000) # Should be ready
if data:
print('echoing', repr(data), 'to', conn)
conn.send(data) # Hope it won't block
else:
print('closing', conn)
sel.unregister(conn)
conn.close()
sock = socket.socket()
sock.bind(('localhost', 1234))
sock.listen(100)
sock.setblocking(False)
sel.register(sock, selectors.EVENT_READ, accept)
while True:
events = sel.select()
for key, mask in events:
callback = key.data
callback(key.fileobj, mask)
上面示例代码来自官方文档,接下来对关键代码进行重点说明
2. 重点知识说明
(1)conn.setblocking(False)
设置socket的阻塞或非阻塞模式
阻塞模式下当试图对该文件描述符进行读写时,如果当时没有东西可读,或者暂时不可写,程序就进入等待状态,直到有东西可读或者可写为止
非阻塞模式下如果没有东西可读,或者不可写,读写函数马上返回,而不会等待
(2)sel.register(conn, selectors.EVENT_READ, read)
对描述符进行注册,也就是对该描述符的EVENT_READ事件进行监听,当又READ事件通知时,调用回调函数read
selectors库提供了两个监听事件:EVENT_READ和EVENT_WRITE
(3)sel.unregister(conn)
注销描述符
(4)events = sel.select()
函数原型为:abstractmethod select
(timeout=None)
该函数是实现I/O异步的关键,等待,直到一些已注册的文件对象准备就绪,或者超时。
如果timeout>0,则指定最大等待时间,以秒为单位,如果超时没有,则调用将阻塞,直到被监视的文件对象准备就绪。如果timeout< 0,调用将不会阻塞,并将报告当前就绪的文件对象。
该函数返回一个元组(key, events)
key为class selectors.SelectorKey
对象,SelectorKey = namedtuple(‘SelectorKey’, [‘fileobj’, ‘fd’, ‘events’, ‘data’])
fileobj为注册的文件对象
fd为文件描述符
data为与文件对象相关联的自定义数据,如上面的回调函数
明确上面的4个知识点后会觉得selectors库的使用很简单
最后对DefaultSelector进行说明,DefaultSelector会根据当前操作系统类型自己选择selector类型
代码语言:javascript复制if 'KqueueSelector' in globals():
DefaultSelector = KqueueSelector
elif 'EpollSelector' in globals():
DefaultSelector = EpollSelector
elif 'DevpollSelector' in globals():
DefaultSelector = DevpollSelector
elif 'PollSelector' in globals():
DefaultSelector = PollSelector
else:
DefaultSelector = SelectSelector
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/120068.html原文链接:https://javaforall.cn