#coding=utf8 ''' 客户端 udp协议 方法: 1.通过多线程实现停等协议来进行可靠传输, 2.通过压缩、分块实现文件的快速重传 3.服务端接收后进行解压缩操作 ''' import socket import os import hashlib from os.path import basename from threading import Thread,Event from time import sleep import zipfile import gzip #-------------------------------配置-------------------------------------------- #------------------------------config-------------------------------------------- ip='192.168.230.141'#server的ip port=7777 #server的port BUFFER_SIZE= 4*1024*1024 #4G进行分块处理 dst='file.txt' #目的文件夹 port_ack=7778 #发送给server端ack消息的端口 fn_path='output.bin' fn_path_zip=fn_path+".gz" ack_address=(ip,port_ack) #------------------------------大文件压缩------------------------------------------- BufSize = 1024*16 def gZipFile(src, dst): fin = open(src, 'rb') fout = gzip.open(dst, 'wb') in2out(fin, fout) def gunZipFile(gzFile, dst): fin = gzip.open(gzFile, 'rb') fout = open(dst, 'wb') in2out(fin, fout) def in2out(fin, fout): while True: buf = fin.read(BufSize) if len(buf) < 1: break fout.write(buf) fin.close() fout.close() #关闭文件 #------------------------------中间文件------------------------------------------- #用来临时保存数据 data=set() #接收数据的socket sock_recv=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) sock_recv.bind(('',port)) #确认反馈地址 sock_ack=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) #重复收包次数 repeat=0 while True: buffer,_=sock_recv.recvfrom(BUFFER_SIZE) #全部接收完成,获取文件名 if buffer.startswith(b'over_'): fn=buffer[5:].decode() #多确认几次文件传输结束,防止发送方丢包收不到确认 for i in range(5): sock_ack.sendto(fn.encode()+b'_ack',ack_address) break buffer=tuple(buffer.split(b'_',maxsplit=1)) if buffer in data: repeat=repeat+1 else: data.add(buffer) sock_ack.sendto(buffer[0]+b'_ack',ack_address) sock_recv.close() sock_ack.close() data=sorted(data,key=lambda item:int(item[0])) with open(fn,'wb') as fp: for item in data: fp.write(item[1]) #gunZipFile(fn_path_zip,dst)