Py修行路 socket + select 实现 异步IO模块
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Py修行路 socket + select 实现 异步IO模块相关的知识,希望对你有一定的参考价值。
对于异步IO请求的本质则是【非阻塞Socket】+【IO多路复用】,那我们是否可以自定义异步IO模块?
自定义一个插件,模块如下:
import socket import select class Request(object): """ select监听的是有变化的对象,当多个socket通信存在的话,当发生变化时,无法确定哪个是哪个。此时就需要唯一指定哪个通信处理的是什么数据! 我们想到的办法是,再另创建一个类,用于接收当前的socket和信息,实例化唯一的对象! 巧妙之处就在于唯一化的处理,生成的每个对象都是唯一的!!! """ def __init__(self,sock,info): #初始化 self.sock = sock 通信 self.info = info 信息 def fileno(self): #转换成fileno对象 return self.sock.fileno() class NoBlockIO(object): def __init__(self): self.sock_list = [] self.conns = [] def add_request(self,req_info): """ 创建请求 假设:req_info = {‘host‘: ‘www.baidu.com‘, ‘port‘: 80, ‘path‘: ‘/‘}, :return: """ sock = socket.socket() #创建socket对象 sock.setblocking(False) #设置为非阻塞 #建立连接,因为是非阻塞状态,连接可能会出异常所以做异常处理。 #此处一定要注意,连接的请求已发出! try: sock.connect((req_info[‘host‘],req_info[‘port‘])) except BlockingIOError as e: pass #实例化唯一的通信对象 obj = Request(sock,req_info) #将生成的sock对象和信息列表传递到Request类,然后获取对应的文件句柄,信息保留到 self.sock_list.append(obj) #将得到的对象添加到sock_list 通信列表中 self.conns.append(obj) #将得到的对象添加到conns 连接列表中 def run(self): """ 开始事件循环,检测:连接成功?数据是否返回? 注意此处操作的就全是Request类生成的对象!!! :return: """ while True: # select.select([request对象,]) r,w,e = select.select(self.sock_list,self.conns,[],0.05) # w,是否连接成功 for obj in w: # 检查obj:request对象 # socket, {‘host‘: ‘www.baidu.com‘, ‘port‘: 80, ‘path‘: ‘/‘}, data = "GET %s http/1.1\\r\\nhost:%s\\r\\n\\r\\n" %(obj.info[‘path‘],obj.info[‘host‘]) #发送GET请求的信息 obj.sock.send(data.encode(‘utf-8‘)) #发送字节数据 self.conns.remove(obj) #然后在连接列表中删除这个对象,排除循环通信的可能 # 数据返回,接收到数据 for obj in r: response = obj.sock.recv(8096) #接收返回的信息 obj.info[‘callback‘](response) #指定对应对象执行回调函数,参数为返回的信息 self.sock_list.remove(obj) #在监听列表中移除这个对象 # 所有请求已经返回 if not self.sock_list: #所有请求都处理完,就退出循环 break
调用这个插件,使用插件里的方法:
from .NBIO import NoBlockIO #自定义定义回调函数,对返回的信息进行处理(执行完毕之后,对数据进行什么操作) def done1(response): print(response) def done2(response): print(response) #准备执行的信息,域名,端口号,回调函数 url_list = [ {‘host‘: ‘www.baidu.com‘, ‘port‘: 80, ‘path‘: ‘/‘,‘callback‘: done1}, {‘host‘: ‘www.cnblogs.com‘, ‘port‘: 80, ‘path‘: ‘/index.html‘,‘callback‘: done2}, {‘host‘: ‘www.bing.com‘, ‘port‘: 80, ‘path‘: ‘/‘,‘callback‘: done2}, ] #实例化一个对象 noblockObj = NoBlockIO() #循环要处理的信息 for item in url_list: noblockObj.add_request(item) #为条信息创建请求 noblockObj.run() #执行
慎重说明:必须知道和理解整个执行的流程!!!
以上是关于Py修行路 socket + select 实现 异步IO模块的主要内容,如果未能解决你的问题,请参考以下文章