基于selectors实现客户端并发下载文件
2022-05-06 15:26 six-eight 阅读(31) 评论(0) 收藏 举报主要知识点:
yield 实现协程。
server端源码:
1 import selectors 2 from socket import * 3 import time 4 import os 5 import struct 6 7 tasks = [] 8 9 def accept(sk): 10 conn, addr = sk.accept() 11 ds.register(conn, selectors.EVENT_READ, read) 12 13 def get(conn, filename): 14 conn.send(struct.pack('i', os.path.getsize(filename))) 15 with open(filename, 'rb') as f: 16 while True: 17 data = f.read(1024) 18 if not data: 19 break 20 conn.send(data) 21 yield 22 23 def read(conn): 24 data = conn.recv(1024) 25 if not data: 26 ds.unregister(conn) 27 conn.close() 28 else: 29 cmd = data.decode('utf-8') 30 if cmd[0:3] == 'get': 31 c = get(conn, cmd[4:]) 32 c.__next__() 33 tasks.append(c) 34 35 if __name__ == '__main__': 36 sk = socket(AF_INET, SOCK_STREAM) 37 sk.bind(('127.0.0.1', 8082)) 38 sk.listen(5) 39 ds = selectors.DefaultSelector() 40 ds.register(sk, selectors.EVENT_READ, accept) 41 while True: 42 events = ds.select(timeout=0.05) 43 for key, mask in events: 44 key.data(key.fileobj) 45 for task in tasks: 46 try: 47 task.send(1) 48 except StopIteration: 49 tasks.remove(task) 50 51 52
client端源码:
1 from socket import * 2 import struct 3 4 5 sk = socket(AF_INET, SOCK_STREAM) 6 7 sk.connect(('127.0.0.1', 8082)) 8 9 while True: 10 msg = input(">>>>") 11 if not msg: continue 12 sk.send(msg.encode('utf-8')) 13 filesize = struct.unpack('i', sk.recv(4))[0] 14 has_receive = bytes() 15 while len(has_receive) < filesize: 16 has_receive += sk.recv(1024) 17 with open(msg[4:], 'wb') as f: 18 f.write(has_receive)
浙公网安备 33010602011771号