server.py
import selectors import socket import os import time BASE_DIR =os.path.abspath(os.path.dirname(__file__)) class selectFtpserver: def __init__(self): self.dic = {} # 创建空字典 self.hasReceived = 0 self.hasSend=0 self.sel = selectors.DefaultSelector() # 生成一个select对象 self.create_socket() #create_socket()是创建socket对象函数完成绑定功能 self.hanle() #handle()函数完成循环监听 def create_socket(self): sock = socket.socket() sock.bind(('127.0.0.1', 8899)) sock.listen() sock.setblocking(False) self.sel.register(sock, selectors.EVENT_READ, self.accept) # 把刚生成的sock连接对象注册到select连接列表中,并交给accept函数处理 print("服务端已打开,请连接客户端") def hanle(self): while True: events = self.sel.select() # 默认是阻塞,有活动连接就返回活动的连接列表 # 这里看起来是select,其实有可能会使用epoll,如果你的系统支持epoll,那么默认就是epoll # print("event==",events) for key, mask in events: callback = key.data # 去调accept函数 callback(key.fileobj, mask) # key.fileobj就是readable中的一个socket连接对象 def accept(self,sock, mask): conn, addr = sock.accept() # Should be ready print('accepted', conn, 'from', addr) conn.setblocking(False) # 设定非阻塞 self.sel.register(conn, selectors.EVENT_READ, self.read) # 新连接注册read回调函数 self.dic[conn] = {} # 在空字典里进行了conn赋值,self.dic={conn:{},} def read(self, conn, mask): # 接收了conn和mask try: # 加异常防止客户端突然断开 if not self.dic[conn]: # 判断self.dic[conn]里面是否是空字典,如果是空字典,代表第一次进来 print('====第一次进来') data = conn.recv(1024) # conn接收了客户端发来的数据 print("data==",str(data, encoding='utf-8')) cmd, filename,filesize = str(data, encoding='utf-8').split('|') # 把接收到客户端发来的包解开拿到cmd,filename,filesize个信息 self.dic = {conn: {"cmd": cmd, "filename": filename, "filesize": int(filesize)}} # 把拿到的cmd,filename,filesize信息放到self.dic字典里去后程序返回到handle()函数里的events继续监听 print(self.dic) if cmd == 'put': # 如果接收的信息是put conn.send(bytes("OK", encoding='utf8')) # 给客户端返回一条数据 if self.dic[conn]['cmd'] == 'get': file = os.path.join(BASE_DIR, "upload", filename) if os.path.exists(file): print("文件存在的情况,返回YES给客户端") filesize = os.path.getsize(file) self.dic[conn]['filesize'] = filesize print("self.dic",self.dic) send_info = '%s|%s' % ('YES', filesize) conn.send(bytes(send_info, encoding='utf8')) else: print("文件不存在情况下") send_info = '%s|%s' % ('NO', 0) conn.send(bytes(send_info, encoding='utf8')) self.dic[conn] = {} #文件不存在的情况下,要将清空字典 else: # 如果不是空字典代表不是第一次进来 print('不是第一次来的') print(self.dic) if self.dic[conn].get('cmd', None): # 对接收的命令进行分发判断是put还是get cmd = self.dic[conn].get('cmd') if hasattr(self, cmd): # 如果cmd=put调用put函数,如果是cmd=get函数调用get函数 func = getattr(self, cmd) func(conn) else: print("error cmd!") conn.close() else: print("error cmd!") conn.close() except Exception as e: print('断开的客户端信息是:', conn) self.sel.unregister(conn) # 如果没有接收到数据做一个关闭解除 conn.close() # put上传函数 def put(self, conn): fileName = self.dic[conn]['filename'] fileSize = self.dic[conn]['filesize'] # print("BASE_DIR",BASE_DIR) path = os.path.join(BASE_DIR, "upload", fileName) # 拿到要接收的信息 # print(fileName,fileSize,path) recv_data = conn.recv(1024) # 接收客户端上传的数据1024字节 self.hasReceived += len(recv_data) # 把接收的数据累加到变量self.hasReceived with open(path, 'ab') as f: # 打开文件 f.write(recv_data) # 把接收的数据写到文件里去 if fileSize == self.hasReceived: # 判断文件大小跟接收大小是否一样 if conn in self.dic.keys(): # 如果文件大小跟接收大小一样清空字典 self.dic[conn] = {} self.hasReceived = 0 #S上传结束之后,需要将self.hasReceived 重置成功 print("%s 上传完毕!" % fileName) def get(self,conn): fileName = self.dic[conn]['filename'] file = os.path.join(BASE_DIR, "upload", fileName) # fileSize = os.path.getsize(file) fileSize=self.dic[conn]['filesize'] data = conn.recv(1024) # conn接收了客户端发来的数据 dataOK = str(data, encoding='utf-8') if dataOK == 'OK': with open(file, 'rb') as f: # 打开文件 while fileSize > self.hasSend: # 循环的发送文件给客户端 contant = f.read(1024) recv_size = len(contant) conn.send(contant) self.hasSend += recv_size s = str(int(self.hasSend / fileSize * 100)) + "%" print("正在下载文件: " + fileName + " 已经下载:" + s) if fileSize == self.hasSend: # 判断文件大小跟接收大小是否一样 if conn in self.dic.keys(): # 如果文件大小跟接收大小一样清空字典 self.dic[conn] = {} print("%s 下载完毕!" % fileName) self.hasSend = 0 if __name__ == '__main__': selectFtpserver()
client.py
import socket import os,sys BASE_DIR=os.path.dirname(os.path.abspath(__file__)) class selectFtpClient: def __init__(self): self.args=sys.argv #sys.argv在命令行输入的参数,第一个参数默认文件名,第二个参数跟IP地址和端口 if len(self.args)>1: #如果大于1把第二个参数俩个值赋值给port self.port=(self.args[1],int(self.args[2])) else: self.port=("127.0.0.1",8899) #如果没有第二个参数默认取这个 self.create_socket() # self.command_fanout() #进行命令分发 self.mainPath = os.path.join(BASE_DIR, 'filename') # 获取该客户端下的filename路径 #create_socket函数创建socket对象连接服务端 def create_socket(self): try: self.sk = socket.socket() self.sk.connect(self.port) print('连接FTP服务器成功!') except Exception as e: print("eroor:",e) #command_fanout()函数进行命令分发 def command_fanout(self): while True: try: print("----------------welcome to ftp client-------------------") self.help_info() cmd_info = input('>请输入操作命令:').strip() # put 12.png images if not cmd_info: continue cmd,file = cmd_info.split() ##按照空格分隔 # print("命令是什么", cmds) if cmd == "quit": break if hasattr(self, cmd): func = getattr(self, cmd) func(cmd,file) Tag = input("是否继续进入ftp clinet,请选择Y/N:").strip() if Tag.upper() == 'Y': continue else: break else: print('No such command ,please try again') except Exception as e: # server关闭了 print('%s' % e) break def help_info(self): print (''' get + (文件名) 表示下载文件 put + (文件名) 表示上传文件 quit 表示退出登录 ''') #put()上传函数 def put(self,cmd,file): if os.path.isfile(file): #判断本地文件是否存在 fileName = os.path.basename(file) #取出文件的名字 fileSize = os.path.getsize(file) #取出文件的大小 fileInfo = '%s|%s|%s'%(cmd,fileName,fileSize) #给文件名字大小打包成fileInf self.sk.send(bytes(fileInfo, encoding='utf8')) #调用send方法把fileInf发给服务端 recvStatus = self.sk.recv(1024) #接收服务端返回的OK内容 print('recvStatus' , recvStatus) hasSend = 0 if str(recvStatus, encoding='utf8') == "OK": #如果接收到服务端返回的OK with open(file, 'rb') as f: #打开文件 while fileSize > hasSend : #循环的去上传文件 contant = f.read(1024) recv_size = len(contant) self.sk.send(contant) hasSend += recv_size s=str(int(hasSend/fileSize*100))+"%" print("正在上传文件: "+fileName+" 已经上传:" +s) print('%s文件上传完毕' % (fileName,)) else: print('要上传的文件不存在') #get()下载函数 def get(self,cmd,fileName): path = os.path.join(BASE_DIR, "download", fileName) # 拿到要接收的信息 fileSize=0 fileInfo = '%s|%s|%s' % (cmd, fileName, fileSize) # 给文件名字大小打包成fileInf print(fileInfo) self.sk.send(bytes(fileInfo, encoding='utf8')) # 调用send方法把fileInfo发给服务端 recvdata = self.sk.recv(1024) # 接收服务端返回的是否存在文件内容 recvStatus, fileSize = str(recvdata, encoding='utf-8').split('|') print("recvStatus==",recvStatus,fileSize) fileSize = int(fileSize) hasReceived = 0 if recvStatus == "YES": # 如果接收到服务端返回的YES self.sk.send(bytes('OK', encoding='utf8')) # 通知服务端可以正常下载了 while fileSize > hasReceived: # 循环的发送文件给客户端 recv_data = self.sk.recv(1024) # 接收客户端上传的数据1024字节 hasReceived += len(recv_data) # 把接收的数据累加到变量self.hasReceived print("hasReceived",hasReceived) with open(path, 'ab') as f: # 打开文件 f.write(recv_data) # 把接收的数据写到文件里去 if fileSize == hasReceived: # 判断文件大小跟接收大小是否一样 print("%s 下载完毕!" % fileName) recvStatus = 'YESS' else: print('要下载的文件不存在') if __name__=='__main__': selectFtpClient()
以上就是python 基于selectors库实现文件上传与下载的详细内容,更多关于python 上传下载的资料请关注其它相关文章!
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件!
如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
暂无“python 基于selectors库实现文件上传与下载”评论...
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新动态
2024年11月24日
2024年11月24日
- 凤飞飞《我们的主题曲》飞跃制作[正版原抓WAV+CUE]
- 刘嘉亮《亮情歌2》[WAV+CUE][1G]
- 红馆40·谭咏麟《歌者恋歌浓情30年演唱会》3CD[低速原抓WAV+CUE][1.8G]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[320K/MP3][193.25MB]
- 【轻音乐】曼托凡尼乐团《精选辑》2CD.1998[FLAC+CUE整轨]
- 邝美云《心中有爱》1989年香港DMIJP版1MTO东芝首版[WAV+CUE]
- 群星《情叹-发烧女声DSD》天籁女声发烧碟[WAV+CUE]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[FLAC/分轨][748.03MB]
- 理想混蛋《Origin Sessions》[320K/MP3][37.47MB]
- 公馆青少年《我其实一点都不酷》[320K/MP3][78.78MB]
- 群星《情叹-发烧男声DSD》最值得珍藏的完美男声[WAV+CUE]
- 群星《国韵飘香·贵妃醉酒HQCD黑胶王》2CD[WAV]
- 卫兰《DAUGHTER》【低速原抓WAV+CUE】
- 公馆青少年《我其实一点都不酷》[FLAC/分轨][398.22MB]
- ZWEI《迟暮的花 (Explicit)》[320K/MP3][57.16MB]