# 服务端import socketserverimport osimport jsonimport hashlibimport structclass MySocketServer(socketserver.BaseRequestHandler): users = [] @staticmethod def get_dic(): # 获取密码库 user_dic = {} file_name = 'register' if file_name not in os.listdir(os.path.dirname(__file__)): return user_dic else: with open(os.path.join(os.path.dirname(__file__), file_name), mode='r', encoding='utf-8') as f: for line in f: if line: username, psw = line.strip().split('|') user_dic[username] = psw return user_dic def logon(self): # 注册 user_dic = self.get_dic() time = 3 while time > 0: username, psw = self.request.recv(1024).decode('utf-8').split('|') if 0 <= len(username) <= 20 and 6 <= len(psw) <= 20 and (username not in user_dic): with open(os.path.join(os.path.dirname(__file__), 'register'), mode='a', encoding='utf-8') as f: md5 = hashlib.md5() md5.update(psw.encode('utf-8')) f.write(f'{username}|{md5.hexdigest()}\n') self.request.send('True'.encode()) MySocketServer.users.append(username) self.user = username return True else: time -= 1 self.request.send(str(time).encode('utf-8')) return False def login(self): # 登录 time = 3 user_dic = self.get_dic() while time > 0: username, psw = self.request.recv(1024).decode('utf-8').split('|') md5 = hashlib.md5() md5.update(psw.encode('utf-8')) if user_dic.get(username) == md5.hexdigest() and username not in MySocketServer.users: self.request.send('True'.encode()) MySocketServer.users.append(username) self.user = username return True else: time -= 1 self.request.send(str(time).encode('utf-8')) return False def up(self): # 上传 while 1: len_head_dic = struct.unpack('i', self.request.recv(4))[0] head_dic = json.loads(self.request.recv(len_head_dic).decode('utf-8')) file_name = head_dic['file_name'] file_md5 = head_dic['file_md5'] file_size = head_dic['file_size'] if self.user not in os.listdir(os.path.join(os.path.dirname(__file__), '用户文件')): os.makedirs(f'用户文件/{self.user}') file_path = os.path.join(os.path.dirname(__file__), f'用户文件/{self.user}', file_name) with open(file_path, mode='wb') as f: md5 = hashlib.md5() len_data = 0 while len_data < file_size: data = self.request.recv(1024) len_data += len(data) md5.update(data) f.write(data) data_md5 = md5.hexdigest() if data_md5 == file_md5: self.request.send('True'.encode('utf-8')) return True else: self.request.send('False'.encode('utf-8')) def down(self): # 下载 file_path = os.path.join(os.path.dirname(__file__), '用户文件') file_user = os.listdir(file_path) if self.user not in file_user or not os.listdir(os.path.join(file_path, f'{self.user}')): self.request.send('False'.encode('utf-8')) else: file_lst = os.listdir(os.path.join(file_path, f'{self.user}')) file_show = '' for n, file in enumerate(file_lst, 1): file_show += f'序号:{n}\t文件名:{file}\n' to_client = f'可下载文件:\n{file_show}'.encode('utf-8') self.request.send(to_client) while 1: from_client = self.request.recv(1024).decode('utf-8') try: with open(os.path.join(file_path, f'{self.user}', file_lst[int(from_client) - 1]), mode='rb') as f: file_size = 0 md5 = hashlib.md5() while 1: data = f.read(1024) if data: md5.update(data) file_size += len(data) else: break file_md5 = md5.hexdigest() self.request.send('True'.encode('utf-8')) except Exception: self.request.send('False.'.encode('utf-8')) continue else: head_dic = { 'file_md5': file_md5, 'file_name': file_lst[int(from_client) - 1], 'file_size': file_size } head_dic_json_bytes = json.dumps(head_dic).encode('utf-8') len_head_dic_bytes = struct.pack('i', len(head_dic_json_bytes)) self.request.send(len_head_dic_bytes) self.request.send(head_dic_json_bytes) with open(os.path.join(file_path, f'{self.user}', file_lst[int(from_client) - 1]), mode='rb') as f: while 1: data = f.read(1024) if data: self.request.send(data) else: return True def handle(self): while 1: try: from_client = self.request.recv(1024).decode('utf-8') func = getattr(self, from_client) ret = func() if ret == False: break except Exception: MySocketServer.users.remove(self.user) breakserver = socketserver.ThreadingTCPServer(('192.168.13.19', 2020), MySocketServer)server.serve_forever() # 对象执行serve_forever方法,开启服务端
# 客户端import socketimport osimport jsonimport hashlibimport structimport sysimport timedef progress(percent, width=50): # 打印进度条 if percent >= 1: percent = 1 show_str = ('%%-%ds' % width) % (int(width*percent)*'|') print('\r%s %d%%' %(show_str, int(100*percent)), end='')class MyClient: login_logon = {'1': 'login', '2': 'logon'} func_dic = { '1': 'up', '2': 'down', '3': 'exit' } def __init__(self, name, ip, port): self.name = name self.socket = socket.socket() self.socket.connect((ip, port)) def logon(self): # 注册 print('-----欢迎访问注册页面-----') while 1: username = input('请输入用户名:').strip() psw = input('请输入密码:').strip() self.socket.send(f'{username}|{psw}'.encode('utf-8')) from_server = self.socket.recv(1024).decode('utf-8') if from_server == 'True': print('恭喜你,注册成功~~~~~~~~') return True elif from_server == '0': print('啊哈,注册失败了,正在退出....') return False else: print(f'再来一次吧,还有{from_server}次机会~~~~') def login(self): # 登录 print('-----欢迎访问登录页面-----') while 1: username = input('请输入用户名:').strip() psw = input('请输入密码:').strip() self.socket.send(f'{username}|{psw}'.encode('utf-8')) from_server = self.socket.recv(1024).decode('utf-8') if from_server == 'True': print('恭喜你,登录成功~~~~~~~~') return True elif from_server == '0': print('啊哈,登录失败了,正在退出....') return False else: print(f'再来一次吧,还有{from_server}次机会~~~~') def up(self): # 上传 print('-----欢迎访问上传页面-----') while 1: file_path = input('请输入上传的文件路径:').strip() try: with open(file_path, mode='rb') as f: file_size = 0 md5 = hashlib.md5() while 1: data = f.read(1024) if data: md5.update(data) file_size += len(data) else: break file_md5 = md5.hexdigest() except Exception: print('路径错误,请重新输入.') continue else: head_dic = { 'file_md5': file_md5, 'file_name': os.path.basename(file_path), 'file_size': file_size } head_dic_json_bytes = json.dumps(head_dic).encode('utf-8') len_head_dic_bytes = struct.pack('i', len(head_dic_json_bytes)) self.socket.send(len_head_dic_bytes) self.socket.send(head_dic_json_bytes) with open(file_path, mode='rb') as f: data_size = 0 while 1: data = f.read(1024) if data: self.socket.send(data) data_size += len(data) percent = data_size / file_size progress(percent, width=70) else: break from_server = self.socket.recv(1024).decode('utf-8') if from_server == 'True': print('恭喜你,上传成功.') return True else: print('啊哈,上传失败.') def down(self): # 下载 print('-----欢迎访问下载页面-----') from_server = self.socket.recv(1024).decode('utf-8') if from_server == 'False': print('你的云盘为空,请先上传文件~~~~~~') else: print(from_server) while 1: choice = input('请输入选择的序号:').strip().encode('utf-8') self.socket.send(choice) return_from_server = self.socket.recv(1024).decode('utf-8') if return_from_server == 'True': len_head_dic = struct.unpack('i', self.socket.recv(4))[0] head_dic = json.loads(self.socket.recv(len_head_dic).decode('utf-8')) file_name = head_dic['file_name'] file_md5 = head_dic['file_md5'] file_size = head_dic['file_size'] file_path = os.path.join(os.path.dirname(__file__), '下载', file_name) with open(file_path, mode='wb') as f: md5 = hashlib.md5() len_data = 0 while len_data < file_size: data = self.socket.recv(1024) len_data += len(data) md5.update(data) f.write(data) percent = len_data / file_size progress(percent, width=70) percent = len_data / file_size progress(percent, width=70) data_md5 = md5.hexdigest() if data_md5 == file_md5: print('下载成功.') return True else: print('下载失败.') else: print('输入错误,请重新输入.') def exit(self): # 退出 print('正在退出~~~~~~') exit() def run(self): print('-----[1]登录[2]注册-----') while 1: choice = input('请输入选项:').strip() if choice in self.login_logon: self.socket.send(self.login_logon[choice].encode('utf-8')) func = getattr(self, self.login_logon[choice]) ret = func() if ret: while 1: print('-----[1]上传[2]下载[3]退出-----') choice_func = input('请输入选项:').strip() if choice in self.func_dic: self.socket.send(self.func_dic[choice_func].encode('utf-8')) method = getattr(self, self.func_dic[choice_func]) method() else: print('输入错误,请重新输入.') else: break else: print('输入错误,请重新输入.')client = MyClient('客户端', '192.168.13.19', 2020)client.run()