一:实现用户数据上传、下载功能以及MD5验证数据的一致性
法一:
1 import socket 2 import json 3 import hashlib 4 import os 5 import struct 6 7 8 server = socket.socket() 9 10 server.bind(('127.0.0.1',7000)) 11 server.listen(5) 12 13 while True: #服务器服务需要处于打开状态 14 print("server is running ......") 15 conn,addr = server.accept() 16 17 conn.send('欢迎使用文件上传与下载功能'.encode('utf8')) 18 while True:#服务器通讯持续连接状态 19 try: #异常断开处理 20 cmd = conn.recv(1024).decode('utf8') #接受客户端命令此时 21 if cmd == 'exit': #正常退出 22 break 23 if len(cmd) == 0:#若Linux系统异常断开,则退出连接 24 break 25 cmd_list_dcit = json.loads(cmd) #反序列化取出字典内容 26 print(cmd_list_dcit) 27 28 if cmd_list_dcit['command'] == 'put': 29 conn.send('正在上传......'.encode('utf8')) 30 #########################接受数据################## 31 md5 = hashlib.md5() #MD5摘要对象 32 with open(cmd_list_dcit['file_name'],'wb') as f: 33 data_len = 0 34 data_now = '' 35 while data_len < cmd_list_dcit['file_length']: #写入数据 36 data = conn.recv(1024) 37 f.write(data) 38 md5.update(data) #加密数据 39 data_len += len(data) 40 print('已经上传%s'% data_len) 41 ser_md5 = md5.hexdigest() #获取加密数据 42 conn.send('fa'.encode('utf8')) #随意数据,防止黏包 43 client_md5 = conn.recv(1024).decode('utf8') 44 45 if ser_md5 == client_md5: #校验数据 46 print("上传完成") 47 conn.send('已经上传完成'.encode('utf8')) 48 break 49 else: 50 print('上传失败') 51 conn.send('已经上传失败'.encode('utf8')) 52 53 elif cmd_list_dcit['command'] == 'get': 54 md5 = hashlib.md5() #MD5摘要对象 55 with open(cmd_list_dcit['filename'],'rb') as f: 56 file_length = os.path.getsize(cmd_list_dcit['filename'])#文件长度 57 res = struct.pack('i',file_length) 58 conn.send(res) 59 for line in f: #发送要下载的数据 60 print(type(line)) 61 conn.send(line) 62 md5.update(line) 63 server_md5 = md5.hexdigest() 64 conn.recv(1024).decode('utf8')#此地随意接受数据,防止黏包 65 conn.send(server_md5.encode('utf8')) 66 except Exception as e: 67 break 68 conn.close()
1 import socket 2 import json 3 import os 4 import hashlib 5 import struct 6 7 cli = socket.socket() 8 cli.connect(('127.0.0.1',7000)) 9 data = cli.recv(1024).decode('utf8') 10 print(data) 11 class Func: 12 13 def put(self,cmd_list): 14 file_length = os.path.getsize(cmd_list[-1]) #计算上传的文件的大小 15 cmd_list_dcit = {'command':cmd_list[0], 16 'file_name':cmd_list[-1], 17 'file_length':file_length 18 } 19 cmd_command = json.dumps(cmd_list_dcit) #把命令信息序列化成字符串 20 cli.send(cmd_command.encode('utf8')) #发送命令信息 21 ready = cli.recv(1024) 22 print(ready.decode('utf8')) #正在上传..... 23 ###########################上传文件################ 24 md5 = hashlib.md5()#数据校验 25 with open(cmd_list_dcit['file_name'],'rb') as f: #打开文件 26 for line in f: 27 cli.send(line) 28 md5.update(line) 29 while 1: 30 pass 31 32 client_md5 = md5.hexdigest() 33 34 cli.recv(1024).decode('utf8') 35 cli.send(client_md5.encode('utf8'))#发生MD5校验 36 fin = cli.recv(1024) #服务端校验完后发回已经上传完成或者失败 37 print(fin.decode('utf8')) 38 39 def get(self,cmd_list): 40 cmd_dcit = {'command':cmd_list[0], 41 'filename':cmd_list[-1] 42 } 43 cmd_dump = json.dumps(cmd_dcit) 44 cli.send(cmd_dump.encode('utf8')) 45 data_pack = cli.recv(4) 46 data_length = struct.unpack('i',data_pack)[0] #取出要下载的数据的长度 47 data_now_length = 0 48 49 md5 = hashlib.md5() #MD5校验对象 50 with open(cmd_dcit['filename'],'wb') as f : #下载数据 51 while data_now_length < data_length: 52 data_y = cli.recv(1024) 53 data_now_length += len(data_y) 54 f.write(data_y) #写入数据 55 md5.update(data_y) #数据加密 56 print('下载了%s数据'% data_now_length) 57 58 client_md5 = md5.hexdigest() #获取数据密文 59 cli.send('h'.encode('utf8')) #此地放为了放置黏包 60 ser_md5 = cli.recv(1024).decode('utf8') 61 if ser_md5 == client_md5: 62 print("下载成功") 63 else: 64 print("下载失败") 65 66 67 obj = Func() 68 69 cmd = input(">>>") # put xxx 70 cmd_list = cmd.strip().split(' ') # 识别命令 71 if os.path.exists(cmd_list[-1]): 72 if cmd_list[0] == 'put': 73 obj.put(cmd_list) # 上传 74 elif cmd_list[0] == 'get': 75 obj.get(cmd_list) #下载 76 else: 77 print("您输入的文件路径不存在")
最终:加入并发
1 import socket 2 import json 3 import hashlib 4 import os 5 import struct 6 import socketserver 7 8 class Myserver(socketserver.BaseRequestHandler): 9 def handle(self): 10 11 12 while True: # 服务器通讯持续连接状态 13 try: # 异常断开处理 14 print("server is running ......") 15 16 cmd = self.request.recv(1024).decode('utf8') # 接受客户端命令此时 17 if cmd == 'exit': # 正常退出 18 break 19 if len(cmd) == 0: # 若Linux系统异常断开,则退出连接 20 break 21 cmd_list_dcit = json.loads(cmd) # 反序列化取出字典内容 22 print(cmd_list_dcit) 23 24 if cmd_list_dcit['command'] == 'put': 25 self.request.send('正在上传......'.encode('utf8')) 26 #########################接受数据################## 27 md5 = hashlib.md5() # MD5摘要对象 28 with open(cmd_list_dcit['file_name'], 'wb') as f: 29 data_len = 0 30 data_now = '' 31 while data_len < cmd_list_dcit['file_length']: # 写入数据 32 data = self.request.recv(1024) 33 f.write(data) 34 md5.update(data) # 加密数据 35 data_len += len(data) 36 print('已经上传%s' % data_len) 37 38 ser_md5 = md5.hexdigest() # 获取加密数据 39 self.request.send('fa'.encode('utf8')) # 随意数据,防止黏包 40 41 client_md5 = self.request.recv(1024).decode('utf8') 42 print(1) 43 44 if ser_md5 == client_md5: # 校验数据 45 print("上传完成") 46 self.request.send('已经上传完成'.encode('utf8')) 47 break 48 else: 49 print('上传失败') 50 self.request.send('已经上传失败'.encode('utf8')) 51 break 52 53 elif cmd_list_dcit['command'] == 'get': #下载 54 md5 = hashlib.md5() # MD5摘要对象 55 with open(cmd_list_dcit['filename'], 'rb') as f: 56 file_length = os.path.getsize(cmd_list_dcit['filename']) # 文件长度 57 res = struct.pack('i', file_length) 58 self.request.send(res) 59 for line in f: # 发送要下载的数据 60 print(type(line)) 61 self.request.send(line) 62 md5.update(line) 63 server_md5 = md5.hexdigest() 64 self.request.recv(1024).decode('utf8') # 此地随意接受数据,防止黏包 65 self.request.send(server_md5.encode('utf8')) 66 except Exception as e: 67 break 68 self.request.close() 69 70 server = socketserver.ThreadingTCPServer(('127.0.0.1',7000),Myserver) 71 72 server.serve_forever() #accept()
1 import socket 2 import json 3 import os 4 import hashlib 5 import struct 6 7 cli = socket.socket() 8 cli.connect(('127.0.0.1',7000)) 9 10 class Func: 11 12 def put(self,cmd_list): 13 file_length = os.path.getsize(cmd_list[-1]) #计算上传的文件的大小 14 cmd_list_dcit = {'command':cmd_list[0], 15 'file_name':cmd_list[-1], 16 'file_length':file_length 17 } 18 cmd_command = json.dumps(cmd_list_dcit) #把命令信息序列化成字符串 19 cli.send(cmd_command.encode('utf8')) #发送命令信息 20 ready = cli.recv(1024) 21 print(ready.decode('utf8')) #正在上传..... 22 ###########################上传文件################ 23 md5 = hashlib.md5()#数据校验 24 with open(cmd_list_dcit['file_name'],'rb') as f: #打开文件 25 for line in f: 26 cli.send(line) 27 md5.update(line) 28 29 client_md5 = md5.hexdigest() 30 31 cli.recv(1024).decode('utf8') 32 cli.send(client_md5.encode('utf8'))#发生MD5校验 33 fin = cli.recv(1024) #服务端校验完后发回已经上传完成或者失败 34 print(fin.decode('utf8')) 35 cli.close() 36 37 def get(self,cmd_list): 38 cmd_dcit = {'command':cmd_list[0], 39 'filename':cmd_list[-1] 40 } 41 cmd_dump = json.dumps(cmd_dcit) 42 cli.send(cmd_dump.encode('utf8')) 43 data_pack = cli.recv(4) 44 data_length = struct.unpack('i',data_pack)[0] #取出要下载的数据的长度 45 data_now_length = 0 46 47 md5 = hashlib.md5() #MD5校验对象 48 with open(cmd_dcit['filename'],'wb') as f : #下载数据 49 while data_now_length < data_length: 50 data_y = cli.recv(1024) 51 data_now_length += len(data_y) 52 f.write(data_y) #写入数据 53 md5.update(data_y) #数据加密 54 print('下载了%s数据'% data_now_length) 55 56 client_md5 = md5.hexdigest() #获取数据密文 57 cli.send('h'.encode('utf8')) #此地放为了放置黏包 58 ser_md5 = cli.recv(1024).decode('utf8') 59 if ser_md5 == client_md5: 60 print("下载成功") 61 cli.close() 62 else: 63 print("下载失败") 64 cli.close() 65 66 67 obj = Func() 68 69 cmd = input(">>>") # put xxx 70 cmd_list = cmd.strip().split(' ') # 识别命令 71 if os.path.exists(cmd_list[-1]) and cmd_list[0] != 'exit': 72 if cmd_list[0] == 'put': 73 obj.put(cmd_list) # 上传 74 75 elif cmd_list[0] == 'get': 76 obj.get(cmd_list) #下载 77 elif cmd_list[0] == 'exit': 78 cli.send('exit'.encode('utf8')) 79 else: 80 print("您输入的文件路径不存在")
用法:在客户端运行输入get xxx (下载) 或者 put xxx(上传)
法二:仅上传
1 import struct 2 import socket 3 import json 4 import hashlib 5 6 sock=socket.socket() 7 sock.bind(('127.0.0.1',8800)) 8 sock.listen(5) 9 10 while 1: 11 print("server is working....") 12 conn,addr= sock.accept() 13 while 1: 14 15 # 接收json的打包长度 16 file_info_length_pack=conn.recv(4) 17 file_info_length=struct.unpack("i",file_info_length_pack)[0] 18 19 # 接收json字符串 20 file_info_json=conn.recv(file_info_length).decode("utf8") 21 file_info=json.loads(file_info_json) 22 23 action=file_info.get("action") 24 filename=file_info.get("filename") 25 filesize=file_info.get("filesize") 26 27 # 循环接收文件 28 md5=hashlib.md5() 29 with open("put/"+filename,"wb") as f: 30 recv_data_length=0 31 while recv_data_length<filesize: 32 data=conn.recv(1024) 33 recv_data_length+=len(data) 34 f.write(data) 35 # MD5摘要 36 md5.update(data) 37 print("文件总大小:%s,已成功接收%s"%(filesize,recv_data_length)) 38 39 print("接收成功!") 40 conn.send(b"OK") 41 print(md5.hexdigest()) 42 md5_val=md5.hexdigest() 43 client_md5=conn.recv(1024).decode("utf8") 44 if md5_val==client_md5: 45 conn.send(b"203") 46 else: 47 conn.send(b"204")
1 import socket 2 import os 3 import json 4 import struct 5 import hashlib 6 7 sock=socket.socket() 8 sock.connect(("127.0.0.1",8800)) 9 10 11 while 1 : 12 cmd=input("请输入命令:") # put 111.jpg 13 14 action,filename=cmd.strip().split(" ") 15 filesize=os.path.getsize(filename) 16 17 file_info={ 18 "action": action, 19 "filename": filename, 20 "filesize": filesize, 21 } 22 file_info_json=json.dumps(file_info).encode("utf8") 23 24 ret=struct.pack("i",len(file_info_json)) 25 # 发送 file_info_json的打包长度 26 sock.send(ret) 27 # 发送 file_info_json字节串 28 sock.send(file_info_json) 29 # 发送 文件数据 30 md5=hashlib.md5() 31 with open(filename,"rb") as f: 32 for line in f: 33 sock.send(line) 34 md5.update(line) 35 36 data=sock.recv(1024) 37 print(md5.hexdigest()) 38 md5_val=md5.hexdigest() 39 sock.send(md5_val.encode("utf8")) 40 is_valid=sock.recv(1024).decode('utf8') 41 if is_valid=="203": 42 print("文件完整!") 43 else: 44 print("文件上传失败!")
二:实现用户数据上传、一致性校验、进度条、断点续传功能
服务端
1 import socketserver 2 import json 3 import os 4 import hashlib 5 import shutil 6 7 #状态码 8 CODE = { 9 '1001':'从头开始上传文件', 10 '1002':'断点续传', 11 '1003':'上传成功,满足md5校验一致性', 12 '1004':'数据不一致,上传失败' 13 } 14 15 16 class Nbserver(socketserver.BaseRequestHandler): 17 def handle(self): 18 ''' 19 self.request是客户端的socket对象 20 :return: 21 ''' 22 # 1:接受命令 23 upload_cmd_bytes = self.request.recv(1024) 24 25 cmd_dict = json.loads(upload_cmd_bytes.decode('utf-8')) 26 # 2:获取文件信息 27 file_md5 = cmd_dict['file_md5'] 28 file_name = cmd_dict['file_name'] 29 30 file_md5_path = os.path.join(r'E:\python\老男孩\代码\网络编程\20180907\断电续传\home\lilz',file_md5) 31 file_name_path = os.path.join(r'E:\python\老男孩\代码\网络编程\20180907\断电续传\home\lilz',file_name) 32 33 upload_file_size = cmd_dict['size'] 34 35 # 3:判断文件是否存在 36 exist = os.path.exists(file_md5_path) 37 if not exist: #从头传 38 # 3.1通知客户端,可以开始上传了,已经准备好了 39 response = {'code': 1001} 40 self.request.sendall(json.dumps(response).encode('utf-8')) #发对应状态码 41 42 # 3.1.1接受客户端上传的数据 43 md5 = hashlib.md5() 44 45 with open(file_md5_path,mode='ab')as f: 46 recv_size = 0 47 while recv_size < upload_file_size: 48 data = self.request.recv(1024) 49 f.write(data)#写到内存 50 f.flush() #刷到内存 51 recv_size += len(data) 52 md5.update(data) 53 54 MD5 = md5.hexdigest() 55 56 # 3.1.3校验改名字 57 if file_md5 == MD5 : 58 self.request.sendall(b'1003') #数据一致 59 60 if not os.path.exists(file_name_path):#如果不存在此文件名 61 shutil.move(file_md5_path,file_name_path) 62 else: #如果存在此文件名 63 shutil.move(file_md5_path, file_name_path)#暂时未改 64 65 else : 66 self.request.sendall(b'1004') #数据不一致 67 else: #断点续传+大小 68 # 3.2通知客户端,可以开始断点上传 69 exist_size = os.stat(file_md5_path).st_size 70 response = {'code':1002,'size':exist_size} 71 self.request.sendall(json.dumps(response).encode('utf-8')) # 发对应状态码 72 73 with open(file_md5_path, mode='ab')as f: 74 recv_size = exist_size 75 while recv_size < upload_file_size: 76 data = self.request.recv(1024) 77 f.write(data) # 写到内存 78 f.flush() # 刷到内存 79 recv_size += len(data) 80 # 下面进行数据一致性校验 81 md5 = hashlib.md5() 82 with open(file_md5_path, mode='rb')as f1: 83 for line in f1 : 84 md5.update(line) 85 MD5 = md5.hexdigest() 86 if file_md5 == MD5: 87 self.request.sendall(b'1003') # 数据一致 88 shutil.move(file_md5_path, file_name_path) 89 else: 90 self.request.sendall(b'1004') # 数据不一致 91 92 93 94 if __name__ == '__main__': 95 server = socketserver.ThreadingTCPServer(('127.0.0.1',8005), Nbserver) 96 server.serve_forever()
1 import socket 2 import json 3 import hashlib 4 import os 5 import time 6 7 #状态码 8 CODE = { 9 '1001':'从头开始上传文件', 10 '1002':'断点续传' 11 } 12 13 def file_md5(file_path): 14 15 obj = open(file_path,'rb') 16 md5 = hashlib.md5() 17 for line in obj: 18 md5.update(line) 19 obj.close() 20 21 return md5.hexdigest() 22 23 24 25 sk = socket.socket() 26 sk.connect(('127.0.0.1',8005)) 27 28 29 while True: 30 cmd = input('请输入要执行的命令') 31 #1.自定义协议{'cmd':upload,'file_path':'..'} 32 #需要MD5值,如果文件名重复怎么办呢,服务端用MD5当文件名 33 file_path = r'E:\python\老男孩\代码\网络编程\20180907\断电续传\client\1.jpg' 34 print(os.path.exists(file_path)) 35 file_md5_val = file_md5(file_path) 36 file_name = os.path.basename(file_path) 37 file_size = os.stat(file_path).st_size 38 39 cmd_dict = {'cmd':'upload','file_name':file_name,'size':file_size,'file_md5':file_md5_val} 40 upload_cmd_bytes = json.dumps(cmd_dict).encode('utf-8') 41 sk.sendall(upload_cmd_bytes) 42 43 # 2:等待服务端的响应 44 response = json.loads(sk.recv(1024).decode('utf-8'))#得到状态码 45 if response['code'] == 1001: 46 #从头开始,文件迭代或者按下面方式想让它读多少就读多少 47 with open(file_path,mode='rb') as f : 48 send_size = 0 49 while send_size < file_size: 50 data = f.read(1024) 51 sk.sendall(data) 52 send_size += len(data) 53 time.sleep(0.1) 54 val = int(send_size / cmd_dict['size']*100) 55 print('\r%s%s%%'% ('#'*val,val),end='') #进度条 56 check = sk.recv(1024) 57 print(type(check)) 58 if check == b'1003': 59 print("数据上传成功") 60 61 else: 62 print("数据上传失败") 63 64 else :#断点续传 65 exist_size = response['size'] 66 with open(file_path, mode='rb') as f: 67 f.seek(exist_size) 68 send_size = exist_size 69 while send_size < file_size: 70 data = f.read(1024) 71 sk.sendall(data) 72 send_size += len(data) 73 time.sleep(0.1) 74 val = int(send_size / cmd_dict['size'] * 100) 75 print('\r%s%s%%' % ('#' * val, val), end='') # 进度条 76 check = sk.recv(1024) 77 print(check) 78 if check == b'1003': 79 print("数据上传成功") 80 81 else: 82 print("数据上传失败")
浙公网安备 33010602011771号