def __init__(self): # run the super initializer Net.__init__(self) # add the specific arguments for a client server self.parser.add_argument('-f', metavar='filename', type=str, help='The filename of a file to write/read') self.parser.add_argument('-a', metavar='address', type=str, help='The ip address of the server') self.parser.add_argument('-w', action='store_true', help='Flag for writing a file') self.parser.add_argument('-r', action='store_true', help='Flag for reading a file') self.parser.add_argument('-k', action='store_true', help='Flag for killing the server') # parse the arguments args = self.parser.parse_args() server_connection = (args.a, args.p) # if you want to kill, open connection, and send kill if args.k: self.sock.sendto(Packet.kill(), server_connection) exit(0) if not path.exists(args.f): print("File not found, please enter a valid filename") exit(0) # Creating connection to server # source port is 0 since the connection has been made yet print("Initiating connection") self.sock.sendto( Packet.request(args.f, args.w, args.p, 0, self.seq_number).binary_combine(), server_connection) self.sock.settimeout(2) try: syn_ack, address = self.sock.recvfrom(1472) read_syn = Packet.read_packet(syn_ack) if read_syn[1]: if read_syn[0] == "Ack Syn": print( "Proper ack received, send ack back, then data/waiting for data" ) self.port = read_syn[3] window_size = read_syn[5] ack = read_syn[2] + len(syn_ack) self.sock.sendto( Packet.ack(self.seq_number, ack, args.p, self.port, window_size, syn=True).binary_combine(), server_connection) if args.w: self.send_data(args.f, window_size, args.a, args.p, self.sock) else: self.receive_data(args.f, self.sock, args.p, window_size, ack, args.a) else: print("Improper ack received, please try connection again") self.sock.close() exit(0) else: print( "Error in the checksum for ack syn, please try connection again" ) self.sock.close() exit(0) except socket.timeout: print("Connection time out, connection not established") exit(0)
def receive_data(self, filename, sock, d_port, win_size, start_ack, d_address): write_file = open('new' + filename, 'wb') last_packet = False MAX_RETRIES = 5 ack = start_ack while not last_packet: error_flag = False retries = 0 packets = [] # Receiving the full window for i in range(win_size): sock.settimeout(2) try: print("Getting packet " + str(len(packets)) + " from the sender") receive_packet, address = sock.recvfrom(1472) packets.append(receive_packet) except socket.timeout as e: if len(packets) == 0: if retries < MAX_RETRIES: print("Receive timeout, retry: " + str(retries)) retries += 1 else: print("Max retries reached, closing connection") sock.close() if packets: for packet in packets: data = Packet.read_packet(packet) if data[1]: if data[0] == "Data": if data[2] == ack: print( "Proper data packet received, writing data..." + str(data[2])) write_data = data[3].tobytes() write_file.write(write_data) ack = Net.up_ack(ack, len(BitArray(packet))) print("New ack :" + str(ack)) else: print( "Improper sequence number received, dumping improper packets" + str(data[2])) packets.clear() elif data[0] == "Fin": if data[2] == ack: print( "Final packet received, writing, acking, then closing connection" ) write_file.write(data[3].tobytes()) ack = Net.up_ack(ack, len(BitArray(packet))) last_packet = True else: print( "Error detected, creating error packet, dumping packets" ) send_packet = Packet.error(0, d_port, self.port, self.seq_number, ack_num=ack, in_message="Checksum error") error_flag = True packets.clear() self.up_sequence_number( len(send_packet.binary_combine())) if not error_flag: send_packet = Packet.ack(self.seq_number, ack, d_port, self.port, win_size) print("Sending ack packet " + str(ack)) sock.sendto(send_packet.binary_combine(), (d_address, d_port)) else: print("No packets received, closing connection") sock.close()
def __init__(self): # Run super initializer Net.__init__(self) # parse the arguments args = self.parser.parse_args() self.port = args.p self.win_size = random.randint(4, 9) while True: self.re_sock() self.sock.bind(('', args.p)) print("Server IP: " + str(self.sock.getsockname()) + "\nPort number: " + str( args.p) + "\nWaiting for connection") self.sock.settimeout(None) message, address = self.sock.recvfrom(1472) decoded_message = Packet.read_packet(message) # Kill packet received if decoded_message[0] == 'end': self.sock.close() exit(0) if decoded_message[1]: if decoded_message[0] == "Syn": print("Connection requested from " + str(address)) print("Sending syn ack...") ack = decoded_message[2] write_flag = decoded_message[3] filename = decoded_message[4] self.sock.sendto(Packet.ack(self.seq_number, ack, address[1], self.port, self.win_size, syn=True).binary_combine(), address) self.sock.settimeout(2) try: message, address = self.sock.recvfrom(1472) decoded_message = Packet.read_packet(message) if decoded_message[1]: if decoded_message[0] == "Ack Syn": print("Three way handshake confirmed") if write_flag: # Since a file added to the server will be preappended with 'new', this needs to be checked as well if path.exists(filename) or path.exists('new'+filename): print("Trying to send a file that already exists, sending error, closing " "connection") return_packet = Packet.error(6, address[1], self.port, self.seq_number) self.sock.sendto(return_packet.binary_combine(), address) else: print("Ready to receive data...") Net.receive_data(self, "new" + filename, self.sock, address[1], self.win_size, ack, address[0]) else: if path.exists('new' + filename): pathname = 'new' + filename else: pathname = filename # Sending a file not found error, this is redundant check if there is a 'new' + filename but if there # isn't one this one checks for the original name if not path.exists(pathname): print("trying to send a file that doesn't exist, sending error, closing " "connection") send_packet = Packet.error(1, address[1], self.port, self.seq_number) self.sock.sendto(send_packet.binary_combine(), address) else: print("Sending data...") Net.send_data(self, pathname, self.win_size, address[0], address[1], self.sock) except socket.timeout as e: print("Syn ack timeout, connection refused")