服务端: import socketserver import json,os import hashlib class MyTCPHandler(socketserver.BaseRequestHandler): def put(self,*args): server_md5=hashlib.md5() '''接收客户端文件''' cmd_dic = args[0] filename = cmd_dic["filename"] filesize = cmd_dic["size"] if os.path.isfile(filename): f = open(filename + ".new","wb") else: f = open(filename , "wb") self.request.send(b"200 ok") received_size = 0 while received_size < filesize: data = self.request.recv(1024) server_md5.update(data) f.write(data) received_size += len(data) else: print("file [%s] has uploaded..." % filename) self.request.send(server_md5.hexdigest().encode()) def get(self,*args): md5_server=hashlib.md5() #接收客户端的信息 cmd_dic=args[0] #得到文件名称 filename=cmd_dic["filename"] #判断是不是个文件 if os.path.isfile(filename): #得到文件大小 file_size=os.stat(filename).st_size #j将文件大小发送给客户端 self.request.send(str(file_size).encode()) #对应客户端的胡写,防止粘包 self.request.recv(1024) #开始发送文件了 f=open(filename,"rb") for line in f : self.request.send(line) md5_server.update(line) #将MD5后的值 发送给客户端 print(md5_server.hexdigest()) self.request.send((md5_server.hexdigest()).encode()) else: print("服务端没有此文件") def handle(self): while True: try: self.data = self.request.recv(1024).strip() print("{} wrote:".format(self.client_address[0])) print(self.data) cmd_dic = json.loads(self.data.decode()) action = cmd_dic["action"] if hasattr(self,action): func = getattr(self,action) func(cmd_dic) except ConnectionResetError as e: print("err",e) break if __name__ == "__main__": HOST, PORT = "localhost", 9997 # Create the server, binding to localhost on port 9999 server = socketserver.ThreadingTCPServer((HOST, PORT), MyTCPHandler) server.serve_forever() 客户端
_author__ = "Alex Li" import socket import json import os import hashlib #用于打印进度条 import sys,time # client.connect(('192.168.16.200',9999)) class FtpClient(object): def __init__(self): self.client = socket.socket() def help(self): msg = ''' ls pwd cd ../.. get filename put filename ''' print(msg) def connect(self, ip, port): self.client.connect((ip, port)) #利用反射,通过输入的字符串 来调用不同的方法 def interactive(self): md5_client=hashlib.md5() # self.authenticate() #执行操作的代码 while True: cmd = input(">>").strip() if len(cmd) == 0: continue cmd_str = cmd.split()[0] if hasattr(self, "cmd_%s" % cmd_str): func = getattr(self, "cmd_%s" % cmd_str) func(cmd) else: self.help() def cmd_put(self, *args): cmd_split = args[0].split() if len(cmd_split) > 1: filename = cmd_split[1] if os.path.isfile(filename): filesize = os.stat(filename).st_size msg_dic = { "action": "put", "filename": filename, "size": filesize, "overridden": True } self.client.send(json.dumps(msg_dic).encode("utf-8")) print("send", json.dumps(msg_dic).encode("utf-8")) # 防止粘包,等服务器确认 server_response = self.client.recv(1024) f = open(filename, "rb") #用于MD5校验 client_md5=hashlib.md5() #用于计算发送了多少数据 clien_size=0 b=0 for line in f: self.client.send(line) client_md5.update(line) clien_size +=len(line) # 计算接收的数据 占 总文件的百分比 a = int(clien_size / filesize * 100) if b != a and a % 2 == 0: # print("%d" % a + "%") sys.stdout.write("#") sys.stdout.flush() else: pass b = a else: print("100%") f.close() #客户端发送数据的md5值 client_md5=client_md5.hexdigest() else: print(filename, "is not exist") server_ma5=self.client.recv(1024) server_ma5=server_ma5.decode() #判断 两边的md5值是否是一致的 if server_ma5==client_md5: print("文件成功上传至服务器") else: print("上传出错") def cmd_get(self, *args): # 用md5对比文件是否一致 md5_clent = hashlib.md5() '''此方法用于下载操作''' # 把输入的命令 按空格分隔 切分成列表 cmd_split = args[0].split() # 如果命令的长度大于0 if len(cmd_split) > 1: # 得到文件名 filename = cmd_split[1] # 服务端那边解析的是一个字典,所以我也写个字典 msg_dic = { "action": "get", "filename": filename } print(msg_dic) # 将动作和文件名发给服务端 self.client.send(json.dumps(msg_dic).encode("utf-8")) print("发送完毕") # 获得服务端文件的大小 size = self.client.recv(1024).decode() print(type(size)) print(size) server_size = int(size) print("获得服务器文件的大小是%s" % server_size) # 胡写一个,防止粘包 self.client.send(b"jiehsou wenjian") # 准备接受 服务端发来的数据 # 已经获取文件的大小 clien_size = 0 if os.path.isfile(filename): f = open(filename + "new", "wb") else: f = open(filename, "wb") #防止重复出现相同的百分比 而设置的变量 b=0 while clien_size < server_size: if server_size - clien_size > 1024: data_size = 1024 else: data_size = server_size - clien_size data=self.client.recv(data_size) md5_clent.update(data) f.write(data) #计算接收过来的数据长度 clien_size += len(data) #计算接收的数据 占 总文件的百分比 a=int(clien_size/server_size*100) if b!=a and a%2==0: # print("%d" % a + "%") sys.stdout.write("#") sys.stdout.flush() else: pass b=a # 接收server过来的md5值 server_md51 = self.client.recv(1024) server_md52 = server_md51.decode() clien_md5= md5_clent.hexdigest() # print("md5_server1--%s" % server_md51) # print("md5_server2--%s" % server_md52) # # print("md5_client--%s" % clien_md5) # print(server_md51==clien_md5) # print(server_md52==clien_md5) if server_md52==clien_md5 : print("100%") else: print("文件可能被篡改,请重新下载") ftp = FtpClient() ftp.connect("localhost", 9997) ftp.interactive()