目录结构
效果图:
1、客户端
1 import socket,hashlib,os,json,sys,time 2 3 4 5 class Ftpclient(object): 6 7 8 def __init__(self): 9 self.client = socket.socket() 10 11 def connect(self,ip,port): 12 self.client.connect((ip, port)) 13 14 15 def help(self): 16 msg=''' 17 ls 18 19 pwd 20 21 cd .. 22 23 get filename 24 25 put filename 26 27 ''' 28 print(msg) 29 30 31 def interactive(self): 32 """ 33 客户端入口 34 :return: 35 """ 36 while True: 37 verify = self.authenticate() #服务器端认证 38 if verify: 39 while True: 40 cmd = input('输入命令 >>').strip() 41 if len(cmd) == 0:continue 42 cmd_str = cmd.split()[0] 43 if hasattr(self,'cmd_%s' %cmd_str): 44 func = getattr(self,'cmd_%s' %cmd_str) 45 func(cmd) 46 else: 47 self.help() 48 49 50 def cmd_put(self,*args): 51 """ 52 上传文件 53 :param args: 54 :return: 55 """ 56 cmd_solit = args[0].split() 57 start_time = self.alltime() # 开始时间 58 if len(cmd_solit) > 1: 59 filename = cmd_solit[1] 60 if os.path.isfile(filename): 61 filesize = os.stat(filename).st_size 62 msg_dic = { 63 'filename':filename, 64 'size':filesize, 65 'overridden':True, 66 'action':cmd_solit[0] 67 } 68 69 self.client.send( json.dumps(msg_dic).encode('utf-8')) 70 server_respinse=self.client.recv(1024) #防止粘包,等服务器确认返回 71 print('文件开始上传',server_respinse) 72 client_size = 0 73 f = open(filename,'rb') 74 for line in f: 75 client_size += self.client.send(line) 76 self.processBar(client_size,filesize) #进度条 77 else: 78 print('文件传输完毕,大小为 %s'%client_size) 79 end_time = self.alltime() # 结束时间 80 print('本次上传花费了%s 秒'%self.alltime(end_time,start_time)) 81 f.close() 82 else: 83 print(filename,'文件不存在') 84 else: 85 print('输入有误!') 86 87 88 def cmd_get(self,*args): 89 """ 90 下载文件 91 :param args: 92 :return: 93 """ 94 cmd_solit = args[0].split() 95 start_time = self.alltime() # 开始时间 96 filename = cmd_solit[1] 97 if len(cmd_solit) > 1: 98 msg_dic = { 99 'filename': filename,100 'size': '',101 'overridden': True,102 'action': cmd_solit[0],103 'file_exist':''104 }105 self.client.send(json.dumps(msg_dic).encode('utf-8'))106 self.data = self.client.recv(1024).strip()107 108 cmd_dic = json.loads(self.data.decode('utf-8'))109 print(cmd_dic)110 if cmd_dic['file_exist']:111 if os.path.isfile(filename):112 f = open(filename + '.new', 'wb')113 else:114 f = open(filename, 'wb')115 116 self.client.send(b'200 ok') #防止粘包,等服务器确认返回117 client_size = 0118 filesize = cmd_dic['size']119 m = hashlib.md5()120 while client_size < filesize:121 data=self.client.recv(1024)122 f.write(data)123 client_size +=len(data)124 m.update(data)125 self.processBar(client_size, filesize)126 else:127 print('下载完毕')128 end_time = self.alltime() # 结束时间129 print('本次下载花费了%s 秒' % self.alltime(end_time, start_time))130 f.close()131 new_file_md5 = m.hexdigest()132 server_file_md5 = self.client.recv(1024)133 print('MD5', server_file_md5,new_file_md5)134 135 else:136 print('下载的 %s文件不存在'%filename)137 138 else:139 print('输入有误!')140 141 142 def cmd_dir(self,*arge):143 cmd_solit = arge[0].split()144 if len(cmd_solit) > 0:145 msg_dic = {146 'action': cmd_solit[0]147 }148 self.client.send(json.dumps(msg_dic).encode())149 cmd_dir = self.client.recv(1024)150 print(cmd_dir.decode())151 152 else:153 print('输入错误!')154 155 156 157 def alltime(self,*args):158 """159 计算上传、下载时间160 :param args:161 :return:162 """163 if args:164 return round(args[0] - args[1])165 else:166 return time.time()167 168 169 def processBar(self,num, total):170 """171 进度条172 :param num:文件总大小173 :param total: 已存入文件大小174 :return:175 """176 rate = num / total177 rate_num = int(rate * 100)178 if rate_num == 100:179 r = '\r%s>%d%%\n' % ('=' * int(rate_num /3), rate_num,)180 else:181 r = '\r%s>%d%%' % ('=' * int(rate_num /3), rate_num,)182 sys.stdout.write(r)183 sys.stdout.flush184 185 186 def authenticate(self):187 """188 用户加密认证189 :return:190 """191 username = input('输入用户名:>>')192 password = input('输入密码:>>')193 m = hashlib.md5()194 if len(username) > 0 and len(password) >0:195 username = ''.join(username.split())196 password = ''.join(password.split())197 m.update(username.encode('utf-8'))198 m.update(password.encode('utf-8'))199 200 m = {201 'username':username,202 'password':password,203 'md5':m.hexdigest()204 }205 self.client.send(json.dumps(m).encode('utf-8'))206 server_user_md5 = self.client.recv(1024).strip()207 print(server_user_md5.decode())208 if server_user_md5.decode() == 'success':209 print('登录成功!')210 return 'ok'211 else:212 print('用户名密码错误!')213 else:214 print('请输入用户名密码')215 216 217 218 f = Ftpclient()219 f.connect('localhost',9999)220 f.interactive()
2、服务器端
1 import socketserver,json,os,hashlib,sys,paramiko 2 3 import settings 4 5 class Mysocketserver(socketserver.BaseRequestHandler): 6 7 8 9 def put(self,*args): 10 ''' 11 接受客户端上传文件 12 :return: 13 ''' 14 cmd_dic = args[0] 15 filename = cmd_dic['filename'] #获取文件名 16 filesize= cmd_dic['size'] #获取文件大小(字节) 17 18 if os.path.isfile(filename): #判断文件是否存在 19 f = open(filename + '.new','wb') 20 else: 21 f = open(filename, 'wb') 22 23 self.request.send(b'200 ok') #防止粘包 24 print('%s 文件开始上传' % self.client_address[0]) 25 received_size = 0 26 while received_size < filesize: 27 data = self.request.recv(1024) 28 f.write(data) 29 received_size += len(data) 30 else: 31 print('文件传输完毕',filename) 32 33 34 def get(self, *args): 35 ''' 36 客户端下载文件 37 :return: 38 ''' 39 msg_dic = { 40 'filename': '', 41 'size': '', 42 'overridden': True, 43 'action': '', 44 'file_exist': '' 45 } 46 47 cmd_solit = args[0] 48 filename = cmd_solit['filename'] 49 file_exist = os.path.isfile(filename) 50 msg_dic['file_exist'] = file_exist 51 print(file_exist) 52 if file_exist: 53 filesize = os.stat(filename).st_size 54 55 msg_dic['filename'] = filename 56 msg_dic['size'] = filesize 57 msg_dic['action'] = cmd_solit['action'] 58 59 self.request.send(json.dumps(msg_dic).encode('utf-8')) 60 server_respang = self.request.recv(1024) #防止粘包 61 print('开始传输',server_respang) 62 f = open(filename,'rb') 63 m = hashlib.md5() 64 for lien in f: 65 m.update(lien) 66 self.request.send(lien) 67 else: 68 print('传输完成') 69 f.close() 70 self.request.send(m.hexdigest().encode()) 71 else: 72 print('文件不存在') 73 self.request.send(json.dumps(msg_dic).encode('utf-8')) 74 75 76 77 def client_authentication(self): 78 """ 79 客户端认证 80 :return: 81 """ 82 self.client_user= self.request.recv(1024).strip() 83 client_xinxi = json.loads(self.client_user.decode('utf-8')) 84 try: 85 with open(settings.school_db_file + client_xinxi['username'],'rb') as f: 86 data = json.load(f) 87 if data['md5'] == client_xinxi['md5']: #判断用户输入是否和服务器端MD5是否一致 88 print('验证成功!') 89 self.request.send('success'.encode()) 90 return 'success' 91 else: 92 self.request.send('error'.encode()) 93 except Exception as e: 94 print('没有此用户',e) 95 self.request.send('error'.encode()) 96 97 98 def dir(self,*args): 99 """100 查看目录101 :param args:102 :return:103 """104 cmd_split = args[0]105 dd=cmd_split['action']106 result_os = os.popen(dd).read()107 self.request.send(result_os.encode())108 109 110 111 def handle(self):112 """113 服务器端入口114 :return:115 """116 while True:117 try:118 success = self.client_authentication()119 if success:120 self.data=self.request.recv(1024).strip()121 cmd_dic = json.loads(self.data.decode('utf-8'))122 action = cmd_dic['action']123 if hasattr(self,action):124 func = getattr(self,action)125 func(cmd_dic)126 except ConnectionResetError as e:127 print('连接断开',self.client_address[0])128 break129 130 131 132 if __name__ == '__main__':133 134 HOST,PORT='localhost',9999135 server=socketserver.ThreadingTCPServer((HOST,PORT),Mysocketserver)136 server.serve_forever()
settings.py 文件
1 import os2 3 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))4 5 DB_FILE = os.path.join(BASE_DIR, "data\\")6 7 school_db_file = os.path.join(DB_FILE)8 print(school_db_file)
data里两个做测试的文件,
1 alex 文件内容:2 {"username": "alex", "password": "123456", "md5": "94e4ccf5e2749b0bfe0428603738c0f9"}
kml123456文件内容:{"username": "kml123456", "password": "123456","md5": "a791650e70ce08896e3dafbaa7598c26"}
到这里差不多就没了,
联系客服