2018-12-04-Python全棧開發-day95-IO多路複用
阿新 • • 發佈:2018-12-13
import socket import select class MakeRequest: '''用來將socket和url資訊以及回撥函式進行封裝''' def __init__(self, sock, host, callback): self.sock = sock self.host = host self.callback = callback def fileno(self): return self.sock.fileno() # 可以放到select中 class AsyncRequest:'''根據發來的host進行訪問''' def __init__(self): # 用來盛放socket物件 self.wlist = [] # 監聽w self.rlist = [] # 監聽r def add_socket(self, host, callback): '''根據host生成socket''' try: sock = socket.socket() sock.setblocking(0) # 設定為非阻塞 sock.connect((host, 80)) #對主機進行連線,預設為80埠 except BlockingIOError as e: pass request = MakeRequest(sock, host, callback) # 將sock以及對應的封裝在一起 self.wlist.append(request) self.rlist.append(request) # 檢測是否連線上了 def run(self): '''執行socket''' while 1: r, w, e= select.select(self.rlist, self.wlist,self.rlist, 0.05) for w in self.wlist: '''對socket物件進行監聽,如果w有動靜,則說明連線上了''' print(w.host, '已經連線上') info = "GET / HTTP/1.0\r\nHost:%s\r\n\r\n" % (w.host) w.sock.send(bytes(info, encoding='utf-8'), ) self.wlist.remove(w) for r in self.rlist: # 用來接收資料 recv = bytes() while 1: try: chunk = r.sock.recv(8096) recv += chunk except Exception as e: break print(recv) r.callback(recv) r.sock.close() self.rlist.remove(r) if len(self.rlist) == 0: # 所有的socket都處理完成 break # 準備介面 def f1(data): print('f1') def f2(data): print('f2') def f3(data): print('f3') '''不同的url可以有不同回撥函式''' url_list = [ {'host': 'www.baidu.com', 'callback': f1}, {'host': 'www.google.com', 'callback': f2}, {'host': 'www.cnblogs.com', 'callback': f3}, ] # 處理回撥函式的時候,可以進行再次封裝,將url和socket封裝在一塊 req = AsyncRequest() for url in url_list: # 先對urllist進行格式改變 req.add_socket(url['host'], url['callback']) req.run()