服务端
import os import selectors import socket class Select_server(): Base_dir=os.path.dirname(os.path.abspath(__file__)) def __init__(self): self.dic={} self.hasreceived=0 self.sel=selectors.DefaultSelector() self.creat_socket() self.handle() def creat_socket(self): server=socket.socket() server.bind(('localhost',8080)) server.listen(5) server.setblocking(0) self.sel.register(server,selectors.EVENT_READ,self.accept) print('开始连接...') def handle(self): while True: events=self.sel.select() for key,mask in events: callback=key.data callback(key.fileobj,mask) def accept(self,sock,mask): conn,addr=sock.accept() print('conn',conn,'from',addr) conn.setblocking(0) self.sel.register(conn,selectors.EVENT_READ,self.read) self.dic[conn]={} def read(self,conn,mask): try: if not self.dic[conn]: fileInfo=conn.recv(1024) cmd,filename,filesize=str(fileInfo,encoding='utf8').split('|') if hasattr(self,cmd): if cmd=='put': conn.send(bytes('OK,服务端准备好上传文件%s'%filename,encoding='utf8')) self.dic[conn]={'cmd':cmd,'filename':filename,'filesize':int(filesize)} elif cmd=='get': file=os.path.join(self.Base_dir,'download',filename) if os.path.exists(file): filesize=os.path.getsize(file) conn.send(bytes('OK|%s'%filesize,encoding='utf8')) self.dic[conn]={'cmd':cmd,'filename':filename} else: conn.send('NO'.encode('utf8')) else: conn.send('WRONG,错误的指令,请重新输入指令'.encode('utf8')) else: conn.send('WRONG,错误的指令,请重新输入指令'.encode('utf8')) else: func=getattr(self,self.dic[conn].get('cmd')) func(conn) except Exception as e: print(e) self.sel.unregister(conn) conn.close() def put(self,conn): filename=self.dic[conn].get('filename') filesize=self.dic[conn].get('filesize') path=os.path.join(self.Base_dir,'upload',filename) try: data=conn.recv(1024) self.hasreceived+=len(data) with open(path,'ab') as f: f.write(data) if self.hasreceived==filesize: if conn in self.dic.keys(): self.dic[conn]={} self.hasreceived=0 print('%s上传完毕'%filename) return except Exception as e: print(e) self.sel.unregister(conn) conn.close() def get(self,conn): filename=self.dic[conn].get('filename') filesize=self.dic[conn].get('filesize') path=os.path.join(self.Base_dir,'download',filename) data=conn.recv(1024) with open(path,'rb') as f: for line in f: conn.send(line) self.dic[conn]={} print('文件下载完毕!') if __name__ == '__main__': Select_server()客户端
import socket import sys import os class Select_Client(): Base_dir=os.path.dirname(os.path.abspath(__file__)) def __init__(self): arg=sys.argv if len(arg)>2: self.ip=(arg[1],int(arg[2])) else: self.ip=(('218.197.223.92',8080)) if self.creat_socket(): self.handle() def creat_socket(self): self.sk=socket.socket() try: self.sk.connect(self.ip) print('成功连接到服务端',self.ip) return True except Exception as e: print('Error',e) print('请重启客户端') return False def handle(self): while True: print('请输入指令') data=input('>>:').strip() if data=='exit()':exit() cmd,path=data.split(' ',1) if hasattr(self,cmd): func=getattr(self,cmd) func(cmd,path) else: print('无效的指令,请重新输入') def put(self,cmd,path): try: filename=os.path.basename(path) filesize=os.path.getsize(path) except Exception as e: print(e) return fileInfo='%s|%s|%s'%(cmd,filename,filesize) self.sk.send(fileInfo.encode('utf8')) message=self.sk.recv(1024).decode('utf8') print(message) if 'OK' in message: hassend=0 with open(path,'rb') as f: while hassend<filesize: data=f.read(1024) self.sk.send(data) hassend+=len(data) rate=hassend/filesize*100 sys.stdout.write('\r %.2f%% %s'%(rate,'*'*int(rate)))#\r将指针指向开头,所以每次都会覆盖输出 print('\n%s上传成功'%filename) else: return def get(self,cmd,filename): self.sk.send(bytes('%s|%s|0'%(cmd,filename),encoding='utf8')) message=self.sk.recv(1024).decode('utf8') if 'OK' in message: self.sk.send(b'Ready') print('OK,服务端准备好下载文件%s'%filename) filesize=int(message.split('|')[1]) path=os.path.join(self.Base_dir,'download',filename) hasreceived=0 with open(path,'wb') as f: while hasreceived<filesize: data=self.sk.recv(1024) f.write(data) hasreceived+=len(data) rate=hasreceived/filesize*100 sys.stdout.write('\r%.2f%% %s'%(rate,'*'*int(rate))) print('\n%s下载成功'%filename) else: print('文件%s不存在,请重新输入指令'%filename) return if __name__ == '__main__': Select_Client()