You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
teamwk123/users/qinziyao/client.py

97 lines
2.3 KiB

1 month ago
#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)