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.
 
 
 

64 lines
2.1 KiB

  1. import argparse
  2. import math
  3. import os
  4. import socket
  5. MSS = 20476 # MSS = Server buffer size (20480) - data header size (4)
  6. def await_ack(packet):
  7. s.settimeout(1)
  8. while True:
  9. try:
  10. data, addr = s.recvfrom(1024)
  11. print(f"Server: {data.decode()}")
  12. received_ack_seqno = int(data[2:3].decode())
  13. expected_ack_seqno = (int(packet[2:3].decode()) + 1) % 2
  14. if received_ack_seqno != expected_ack_seqno:
  15. continue
  16. return True
  17. except KeyboardInterrupt:
  18. print("Client: Exiting...")
  19. exit()
  20. except socket.timeout: # Expected ACK was not received within one second
  21. print(f"Client: Retransmitting...")
  22. s.sendto(packet, (server_ip, server_port))
  23. if __name__ == "__main__":
  24. parser = argparse.ArgumentParser()
  25. parser.add_argument("server_addr", type=str)
  26. parser.add_argument("file_path", type=str)
  27. args = parser.parse_args()
  28. server_ip, server_port = args.server_addr.split(":")
  29. server_port = int(server_port)
  30. file_name = args.file_path.split(os.path.sep)[-1]
  31. file_size = os.path.getsize(args.file_path)
  32. with socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM) as s:
  33. s.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 30000)
  34. # Check file existence
  35. if not os.path.exists(args.file_path):
  36. print(f"Client: no such file: {args.file_path}")
  37. exit()
  38. # Send start packet to server
  39. packet = f"s|0|{file_name}|{file_size}".encode()
  40. print(f"Client: {packet.decode()}")
  41. s.sendto(packet, (server_ip, server_port))
  42. # Wait for ACK for the given packet
  43. await_ack(packet)
  44. # Upload file to server
  45. seqno = 1
  46. with open(args.file_path, "rb") as f:
  47. for i in range(math.ceil(file_size / MSS)):
  48. print(f"Client: d|{seqno}|chunk{i + 1}")
  49. packet = bytes(f"d|{seqno}|", "utf-8") + f.read(MSS)
  50. s.sendto(packet, (server_ip, server_port))
  51. await_ack(packet)
  52. seqno = (seqno + 1) % 2