python 学习分享-实战篇高级的ftp
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python 学习分享-实战篇高级的ftp相关的知识,希望对你有一定的参考价值。
#server代码 import socketserver,os,hashlib Base_paht = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + ‘/db‘ class Server_ftp(socketserver.BaseRequestHandler): def handle(self): while 1: try: self.username = self.request.recv(1024).strip() #接受用户信息 if not self.username:continue self.username_path = Base_paht + ‘/%s/‘ % self.username.decode() #获取用户文件地址 print(self.username.decode(), ‘连接成功!‘) #打印用户连接信息 self.request.send(‘连接服务器成功!‘.encode()) while 1: try: self.data = self.request.recv(1024).strip() #接受客户端命令 print(‘-->‘,self.data) if not self.data :continue print(‘{} wrote:‘.format(self.client_address[0]),self.username)#打印ip及用户名称 cmd_dic = self.data.decode() #命令编码 print(‘执行的命令为‘,cmd_dic) if hasattr(self,cmd_dic + ‘_file‘): #判断是否存在这条命令 self.request.send(‘{}命令可以被执行‘.format(cmd_dic).encode()) func = getattr(self,cmd_dic + ‘_file‘) #反射 func() else: self.request.send(‘no‘.encode()) #不存在发送错误信息 except ConnectionResetError as e: # print(‘err‘,e) break except ConnectionResetError as e: print(self.client_address[0],e) break def get_file(self): filename = self.request.recv(1024).decode() print(‘客户端想要获取的文件名称为:‘,filename) if os.path.isfile(self.username_path + filename) : file_size = os.stat(self.username_path + filename).st_size #确认文件大小 self.request.send(str(file_size).encode()) #发送文件大小 self.request.recv(1024) #接收please give me f = open(self.username_path + filename,‘rb‘) self.request.send(f.read()) f.close() confirm = self.request.recv(1024).decode() print(confirm) f_1 = open(self.username_path + filename, ‘rb‘) m2 = hashlib.md5() m2.update(f_1.read()) f_1_m2 = m2.hexdigest() f.close() self.request.send(f_1_m2.encode()) print(self.request.recv(1024).decode()) else: self.request.send(‘no‘.encode()) #如果文件不存在,发送no信息 def put_file(self): filename = self.request.recv(1024).decode() if filename != ‘no‘ : self.request.send(‘服务器收到文件名称!‘.encode()) file_size = self.request.recv(1024).decode() self.request.send(‘服务器收到文件大小为{}‘.format(file_size).encode()) f = open(self.username_path + filename,‘wb‘) #直接写入,如果有就覆盖 confirm_size = 0 while confirm_size < int(file_size): if int(file_size) - confirm_size > 1024: # 确保接受的准确性,拒绝粘包. cal = 1024 else: cal = int(file_size) - confirm_size data = self.request.recv(cal) confirm_size += len(data) f.write(data) f.close() f_1 = open(self.username_path + filename,‘rb‘) m2 = hashlib.md5() m2.update(f_1.read()) f_1_m2 = m2.hexdigest() f_1.close() self.request.send(f_1_m2.encode()) print(self.request.recv(1024).decode()) self.request.send(‘{}上传完成‘.format(filename).encode()) # 返回服务器信息,表示下载完成 else: print(‘客户端传送错误文件名称!‘) def open_file(self): filename = self.request.recv(1024).decode() self.request.send(‘服务器收到目录名称!‘.encode()) self.request.recv(1024) #防止粘包 if os.path.exists(self.username_path + filename ): self.request.send(‘yes‘.encode()) self.request.recv(1024) path_dir = os.listdir(self.username_path+ filename) if path_dir == []: # 如果为空 self.request.send(‘nothing‘.encode()) else: self.request.send(str(path_dir).encode()) else: self.request.send(‘no‘.encode()) def look_file(self): self.request.recv(1024) #接收返回的数据,防止粘包 path_dir = os.listdir(self.username_path) if path_dir == []: #如果为空 self.request.send(‘nothing‘.encode()) else: self.request.send(str(path_dir).encode()) if __name__ ==‘__main__‘: HOST,PORT = ‘localhost‘ , 6969 server = socketserver.ThreadingTCPServer((HOST,PORT),Server_ftp) print(‘----------->等待连接<------------‘) server.serve_forever()
#client代码 import socket,os,pickle,hashlib,sys floder_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + ‘/user_floder‘ user_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + ‘/conf‘ server_db_path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + ‘/server_ftp/db/‘ class Scoket_ftp(object): # 客户端类 def __init__(self): self.client = socket.socket() def client_user_register(self): #用户注册 username = input(‘请输入用户名:‘).strip() password = input(‘请输入密码:‘).strip() if not os.path.exists(user_path + ‘/%s‘%username) : pwd_md = hashlib.md5() #md5加密用户密码 pwd_md.update(bytes(password,encoding=‘utf-8‘)) pwd_save = pwd_md.hexdigest() pickle.dump({‘username‘:username,‘password‘:pwd_save},open(user_path + ‘/%s‘%username,‘wb‘)) os.makedirs(server_db_path + username) print(‘创建成功!‘) else: print(‘账户已经存在!‘) def client_user_login(self): #身份验证 username = input(‘请输入用户名:‘).strip() password = input(‘请输入密码:‘).strip() if os.path.exists(user_path + ‘/%s‘%username) : pwd_md = hashlib.md5() # md5加密用户密码 pwd_md.update(bytes(password,encoding=‘utf-8‘)) pwd_save = pwd_md.hexdigest() user_dic = pickle.load(open(user_path + ‘/%s‘%username,‘rb‘)) if username == user_dic[‘username‘] and pwd_save == user_dic[‘password‘] : print(‘%s登录成功‘%username) return username else: print(‘账户密码错误!‘) return False else: print(‘账户密码错误!‘) return False def client_conn(self,ip_addr,port): #建立连接 while 1: username = self.client_user_login() if username : self.client.connect((ip_addr, port)) self.client.send(username.encode()) print(self.client.recv(1024).decode()) break else: continue def help(self): #帮助信息 print(‘‘‘ -----------help----------- look:查看当前目录下文件 open foldername:打开文件夹 get filename:下载文件 put filename:上传文件 ‘‘‘) def client_interaction(self): #交互 while 1: self.help() cmd = input(‘请输入操作命令:‘).strip() if len(cmd.split()) == 1: #判断命令行长度,如果是1的话,在判断输入 if cmd == ‘look‘: self.file_look()#使用look方法 elif cmd == ‘exit‘: self.file_exit() else: print(‘命令输入错误,请重新输入‘) continue elif len(cmd.split()) == 2: #长度为2,证明是带有前面的语句的 cmd_option, filename = cmd.split() if hasattr(self,‘file_‘ + cmd_option): func = getattr(self,‘file_‘ +cmd_option) func(filename) else: continue else: continue def file_look(self): #查看 self.client.send(‘look‘.encode()) #发送方法 print(self.client.recv(1024).decode()) # 服务器确认信息,后面可以加入判断,判断服务器目前状态是否正常 self.client.send(‘please give me!‘.encode()) # 自动发送给服务器 print(‘文件目录:‘,self.client.recv(1024).decode()) #接收目录信息并打印 def file_get(self,filename): #下载 self.client.send(‘get‘.encode()) #先发送方法 print(self.client.recv(1024).decode()) #服务器确认信息,后面可以加入判断,判断服务器目前状态是否正常 self.client.send(filename.encode()) #再发送文件名称 confirm = self.client.recv(1024).decode() #服务器确认文件是否存在,如果存在返回文件大小,如果不存在,返回no if confirm != ‘no‘: self.client.send(‘please give me!‘.encode()) f = open(floder_path+‘/‘+filename,‘wb‘) #在下载文件夹中创建该文件(如果存在,则替换) confirm_cal = 0 rate = 1 while confirm_cal < int(confirm): if int(confirm) - confirm_cal > 1024: #确保接受的准确性,拒绝粘包. cal = 1024 else: cal = int(confirm) - confirm_cal data = self.client.recv(cal) confirm_cal += len(data) #避免tcp拆包 f.write(data) if int(confirm) > 102400: if confirm_cal > int(confirm)/100*(rate+1) and rate<= 100 : rate += 1 r = ‘\r[%s]%d%%‘ % ("=" * rate, rate) sys.stdout.write(r) sys.stdout.flush() else: continue else: r = ‘[%s]%d%%‘%(‘=‘*100,100) sys.stdout.write(r) f.close() self.client.send(‘{}下载完成‘.format(filename).encode()) # 返回服务器信息,表示下载完成 f_1 = open(floder_path+‘/‘+filename,‘rb‘) #判断一致性 m2 = hashlib.md5() m2.update(f_1.read()) f_1_m2 = m2.hexdigest() f_1.close() f_1_m2_server = self.client.recv(1024).decode() if f_1_m2 == f_1_m2_server : print(‘\n下载完成!‘) self.client.send(‘客户端已经成功获取完整文件!‘.encode()) else: print(‘传输异常‘) self.client.send(‘客户端获取文件不完整或存在异常!‘.encode()) else: print(‘确认信息为no,文件可能不存在或有其他问题!‘) def file_put(self,filename): #上传文件 self.client.send(‘put‘.encode()) # 先发送方法 print(self.client.recv(1024).decode()) # 服务器确认信息,后面可以加入判断,判断服务器目前状态是否正常 if os.path.isfile(floder_path + ‘/‘ + filename): self.client.send(filename.encode()) print(self.client.recv(1024).decode()) #拒绝粘包 cal = os.stat(floder_path + ‘/‘ + filename).st_size #获取文件大小 self.client.send(str(cal).encode()) #发送文件大小信息 print(self.client.recv(1024).decode()) #获取反馈 f = open(floder_path+‘/‘+filename,‘rb‘) #打开文件 self.client.send(f.read()) f.close() f_1 = open(floder_path + ‘/‘ + filename, ‘rb‘) #一致性校验 m2 = hashlib.md5() m2.update(f_1.read()) f_1_m2 = m2.hexdigest() f_1.close() f_1_m2_server = self.client.recv(1024).decode() if f_1_m2 == f_1_m2_server: print(‘上传完成!‘) self.client.send(‘客户端已经成功上传完整文件!‘.encode()) else: print(‘传输异常‘) self.client.send(‘客户端上传文件不完整或存在异常!‘.encode()) print(self.client.recv(1024).decode()) else: self.client.send(‘no‘.encode()) print(‘查无此文件‘) def file_open(self,filename): self.client.send(‘open‘.encode()) # 先发送方法 print(self.client.recv(1024).decode()) # 服务器确认信息,后面可以加入判断,判断服务器目前状态是否正常 self.client.send(filename.encode()) #发送目录名称 print(self.client.recv(1024).decode()) self.client.send(‘防止粘包‘.encode()) confirm = self.client.recv(1024).decode() # 服务器确认文件是否存在,如果存在返回yes,如果不存在,返回no if confirm != ‘no‘: self.client.send(‘please give me!‘.encode()) #自动发送给服务器 file_dir = self.client.recv(1024).decode() print(file_dir) else: print(‘确认信息为no,目录可能不存在或有其他问题!‘) if __name__ == ‘__main__‘ : socket_ftp = Scoket_ftp() option = input(‘‘‘ ---------option---------- 1.创建用户 2.登录 3.退出 ‘‘‘).strip() if option == ‘1‘: socket_ftp.client_user_register() elif option == ‘2‘: socket_ftp.client_conn(‘localhost‘,6969) socket_ftp.client_interaction() elif option == ‘3‘: exit() else: print(‘wrong!‘) exit()
以上是关于python 学习分享-实战篇高级的ftp的主要内容,如果未能解决你的问题,请参考以下文章
一起来学习吧~~100例python题实战提高篇(附带答案)
Framework学习实战高级视频--SystemServer启动FallbackHome篇