1. 程式人生 > >自定義異步IO框架

自定義異步IO框架

llb 方法 utf-8 res response sel 異步io header strong

異步就是回調

異步 = 非阻塞+循環

select只能完成IO多路復用,不能完成異步

IO多路復用--->監聽多個socket對象,這個過程是同步的

利用其特性可以開發異步模塊

異步IO:非阻塞的socket + IO多路復用

自定義異步框架

import socket
import select


class HttpRequest(object):
    def __init__(self, sk, host, callback):
        self.socket = sk
        self.host = host
        self.callback 
= callback def fileno(self): # select監聽的對象,只要內部有fileno()方法,並且返回fileno return self.socket.fileno() class HttpResponse(object): def __init__(self, recv_data): self.recv_data = recv_data self.header_dict = {} self.body = None self.initialize()
def initialize(self): headers, body = self.recv_data.split(b\r\n\r\n, 1) self.body = body header_list = headers.split(b\r\n) for h in header_list: h_str = str(h, encoding=utf-8) v = h_str.split(:, 1) if len(v) == 2: self.header_dict[v[0]]
= v[1] class AsyncRequest(object): def __init__(self): self.conn = [] self.connection = [] def add_request(self, host, callback): try: sk = socket.socket() sk.setblocking(0) sk.connect((host, 80),) except BlockingIOError as e: pass # 把sk、host和callback封裝起來,返回fd給select request = HttpRequest(sk, host, callback) self.conn.append(request) self.connection.append(request) def run(self): while True: rlist, wlist, elist = select.select(self.conn, self.connection, self.conn, 0.05) for w in wlist: # 只要能循環到,表示socket和服務端已經連接成功 print(w.host, 連接成功...) tpl = "GET / HTTP/1.0\r\nHost:%s\r\n\r\n" % (w.host,) w.socket.send(bytes(tpl, encoding=utf-8)) self.connection.remove(w) for r in rlist: recv_data = bytes() while True: try: chunck = r.socket.recv(8096) recv_data += chunck except Exception as e: break # 把返回的數據進行處理,然後交給回調函數 response = HttpResponse(recv_data) r.callback(response) r.socket.close() self.conn.remove(r) if len(self.conn) == 0: break def f1(response): print(保存到文件,response.header_dict) def f2(response): print(保存到數據庫, response.header_dict) url_list = [ {host:www.baidu.com,callback: f1}, {host:cn.bing.com,callback: f2}, {host:www.cnblogs.com,callback: f2}, ] req = AsyncRequest() for item in url_list: req.add_request(item[host],item[callback]) req.run()

自定義異步IO框架