better download speed output
request multiple lost packets via one request add padding to hash response
This commit is contained in:
parent
e997a4fc58
commit
552fe0cfea
65
client.py
65
client.py
@ -1,5 +1,8 @@
|
|||||||
timeout = 1
|
timeout = 0.5
|
||||||
|
local_server = False
|
||||||
serverAddressPort = ("213.47.107.152", 1337)
|
serverAddressPort = ("213.47.107.152", 1337)
|
||||||
|
if local_server:
|
||||||
|
serverAddressPort[0] = "127.0.0.1"
|
||||||
|
|
||||||
possible_value = input("Enter a value: ")
|
possible_value = input("Enter a value: ")
|
||||||
filename = possible_value if (filename := possible_value) else "data.bin"
|
filename = possible_value if (filename := possible_value) else "data.bin"
|
||||||
@ -8,9 +11,18 @@ import socket, struct, select, time, math
|
|||||||
|
|
||||||
import hashlib
|
import hashlib
|
||||||
|
|
||||||
#import brotli #pip install brotlipy
|
#convert bps to Kbps, Mbps, Gbps if they are >= 1000
|
||||||
|
def convert_to_highest_speed(bps):
|
||||||
|
if bps < 1000:
|
||||||
|
return f'{round(bps,2)}bps'
|
||||||
|
elif bps < 1000**2:
|
||||||
|
return f'{round(bps/1000,2)}Kbps'
|
||||||
|
elif bps < 1000**3:
|
||||||
|
return f'{round(bps/1000**2,2)}Mbps'
|
||||||
|
elif bps < 1000**4:
|
||||||
|
return f'{round(bps/1000**3,2)}Gbps'
|
||||||
|
|
||||||
max_frame_payload=508
|
max_frame_payload=1016 #508 is the minimum size for routers to "understand" udp packets, but we can possibly send more data
|
||||||
header = "!L16s"
|
header = "!L16s"
|
||||||
header_size = struct.calcsize(header)
|
header_size = struct.calcsize(header)
|
||||||
max_payload = max_frame_payload - header_size
|
max_payload = max_frame_payload - header_size
|
||||||
@ -58,8 +70,8 @@ while packets > 0 or serverhash == None:
|
|||||||
if ready[0]:
|
if ready[0]:
|
||||||
|
|
||||||
datareceived = UDPClientSocket.recvfrom(max_frame_payload)[0]
|
datareceived = UDPClientSocket.recvfrom(max_frame_payload)[0]
|
||||||
if len(datareceived) == 64:
|
if len(datareceived) == 65:
|
||||||
serverhash = struct.unpack("64s", datareceived)[0]
|
serverhash = struct.unpack("64sx", datareceived)[0]
|
||||||
continue
|
continue
|
||||||
if len(datareceived) != max_frame_payload:
|
if len(datareceived) != max_frame_payload:
|
||||||
print("\nerror bad packet: wrong size",len(datareceived))
|
print("\nerror bad packet: wrong size",len(datareceived))
|
||||||
@ -71,6 +83,7 @@ while packets > 0 or serverhash == None:
|
|||||||
print("\nerror bad packet: received multiple times",seq)
|
print("\nerror bad packet: received multiple times",seq)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
|
||||||
#check if packet is last packet and cut data to last packet size
|
#check if packet is last packet and cut data to last packet size
|
||||||
if seq == total_packets-1:
|
if seq == total_packets-1:
|
||||||
#print("len before cut",len(data))
|
#print("len before cut",len(data))
|
||||||
@ -84,35 +97,57 @@ while packets > 0 or serverhash == None:
|
|||||||
print(data.hex())
|
print(data.hex())
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
#print(seq)
|
||||||
|
#print(data)
|
||||||
|
|
||||||
|
#data = deflate.gzip_decompress(data)
|
||||||
|
|
||||||
data_packets[seq] = data
|
data_packets[seq] = data
|
||||||
|
|
||||||
packets -= 1
|
packets -= 1
|
||||||
else:
|
else:
|
||||||
#collect packets that were not received and send them in one message
|
#collect packets that were not received and send them in n messages
|
||||||
|
#where n is the minimum amount of messages needed to request all packets
|
||||||
|
msg = message
|
||||||
|
lost_packets = []
|
||||||
for i in range(len(data_packets)):
|
for i in range(len(data_packets)):
|
||||||
if data_packets[i] == None:
|
if data_packets[i] == None:
|
||||||
#print("requesting packet", i)
|
lost_packets.append(i)
|
||||||
UDPClientSocket.sendto(str.encode(f"{message}/{i}"), serverAddressPort)
|
|
||||||
|
#split lost_packets into groups of size 508-msg.length bytes
|
||||||
|
current_packets = []
|
||||||
|
for i in range(len(lost_packets)):
|
||||||
|
if len(str(lost_packets[i])) + len(msg) + 1 > max_frame_payload:
|
||||||
|
current_packets.append(msg)
|
||||||
|
msg = message
|
||||||
|
msg += f"/{lost_packets[i]}"
|
||||||
|
|
||||||
|
if len(lost_packets) > 0:
|
||||||
|
timeout *= 2 #increase timeout to relieve internet connection and server
|
||||||
|
current_packets.append(msg)
|
||||||
|
for msg in current_packets:
|
||||||
|
UDPClientSocket.sendto(str.encode(msg), serverAddressPort)
|
||||||
|
#print(f'requested lost packets {msg}')
|
||||||
|
|
||||||
|
|
||||||
if serverhash == None:
|
if serverhash == None:
|
||||||
UDPClientSocket.sendto(str.encode(f"{message}:"), serverAddressPort)
|
UDPClientSocket.sendto(str.encode(f"{message}:"), serverAddressPort)
|
||||||
print(f'{total_packets - packets}/{total_packets} | {math.floor((total_packets - packets)/(time.time()-time_started if (time.time()-time_started)!=0 else 1)*max_payload)}Bps'+'\t'*10, end='\r')
|
download_speed = (total_packets - packets)/(time.time()-time_started if (time.time()-time_started)!=0 else 1)*max_payload
|
||||||
|
print(f'{total_packets - packets}/{total_packets} | {convert_to_highest_speed(download_speed)}'+'\t'*5, end='\r')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
print("finished transfer", end='\r')
|
print("finished transfer" + "\t"*5, end='\r')
|
||||||
|
|
||||||
for packet in data_packets:
|
for packet in data_packets:
|
||||||
sha512.update(packet)
|
sha512.update(packet)
|
||||||
|
|
||||||
sha512 = sha512.hexdigest()
|
sha512 = sha512.hexdigest()
|
||||||
|
|
||||||
print('sha512: %s' % sha512)
|
|
||||||
|
|
||||||
print('server sha512: %s' % serverhash.hex())
|
|
||||||
|
|
||||||
if sha512 != serverhash.hex():
|
if sha512 != serverhash.hex():
|
||||||
print('hash mismatch')
|
print('sha512: %s' % sha512)
|
||||||
|
print('server sha512: %s' % serverhash.hex())
|
||||||
|
print(f'hash mismatch, writing corrupt file to disk: {filename}.corrupt')
|
||||||
with open("received/"+filename+".corrupt", 'wb') as f:
|
with open("received/"+filename+".corrupt", 'wb') as f:
|
||||||
f.write(total_data)
|
f.write(total_data)
|
||||||
exit()
|
exit()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user