Пример #1
0
    def est_connection(self):
        my_syn = Packet(src=self.client_port,
                        dst=self.server_port,
                        seq_num=0,
                        ack_num=0,
                        data=b'',
                        ctrl_bits=0x02)
        packed = my_syn.pkt_pack()
        self.client_socket.sendto(packed, self.server_addr)

        try:
            syn_ack = Packet()
            recv_data = self.client_socket.recv(self.pkt_size)
            syn_ack.pkt_unpack(recv_data)

            if syn_ack.get_ack_bit() and syn_ack.ack_num == 1:
                self.conn_est = True
                print("Client: Sending ACK for SYNACK")
                my_syn = Packet(src=self.client_port,
                                dst=self.server_port,
                                seq_num=0,
                                ack_num=1,
                                data=b'',
                                ctrl_bits=0x10)
                packed = my_syn.pkt_pack()
                self.client_socket.sendto(packed, self.server_addr)
            else:
                print("Client: Connection failed: bad SYNACK")
        except socket.timeout:
            print("Client: Connection failed: timeout")
Пример #2
0
    def recv_img(self, filename):
        """
        Receive an image packet by packet
        Saves image to specified file

        Parameters:
          filename - file location to save image
        """
        recv_data = b''  # packet of byte string data
        save_data = b''  # data to be saved to file
        img_not_recvd = True  # flag to indicate if image has been recieved
        exp_seq = 0  # expected sequence number initially 0
        pkt = Packet()
        self.err_flag = 0
        ack = Packet(-1, "ACK")  # make initial NAK

        # get image data from server until all data received
        while True:
            try:
                if img_not_recvd:
                    print("Server: Ready to receive image", flush=True)

                recv_data = self.server_socket.recv(self.pkt_size)

                pkt.pkt_unpack(recv_data)
                if pkt.seq_num != exp_seq or pkt.csum != pkt.checksum(
                        pkt.seq_num, pkt.data):
                    pass
                else:
                    save_data += pkt.data
                    ack = Packet(exp_seq, "ACK")
                    exp_seq += 1

                ack_pack = ack.pkt_pack()
                self.server_socket.sendto(ack_pack, self.client_addr)

                if img_not_recvd:
                    img_not_recvd = False  # img data began streaming if it reaches this point

            except socket.timeout:
                # if image not recieved yet, keep waiting
                if img_not_recvd:
                    pass
                # image has been recieved
                else:
                    # write data into a file
                    with open(filename, 'wb+') as server_img:
                        server_img.write(save_data)
                    print("Server: Received and saved image", flush=True)
                    break  # exit loop
Пример #3
0
    def send_img(self, filename):
        """
        Sends the image packet by packet

        Parameters:
          filename - file to send
        """
        recv_data = b''       # bytes for data received
        recv_pkt = Packet()   # init empty packet for received data
        read_data = b''       # byte string data read from file
        seq_num = 0           # init sequence number

        # open file to be sent
        print("Client: Sending image to Server")
        with open(filename, 'rb') as img:
            read_data = img.read(self.data_size)
            # pack
            send_pkt = Packet(seq_num=seq_num, data=read_data)
            packed = send_pkt.pkt_pack()

            # send data until end of file reached
            while read_data:
                self.client_socket.sendto(packed, self.server_addr)
                #print("Client: Sent:", send_pkt)

                # wait for ACK
                recv_data = self.client_socket.recv(self.pkt_size)
                recv_pkt.pkt_unpack(recv_data)

                #print("Client: Received message:", recv_pkt)

                # Received NAK or incorrect ACK
                if recv_pkt.seq_num != seq_num or recv_pkt.csum != recv_pkt.checksum(recv_pkt.seq_num, recv_pkt.data):
                    pass
                # ACK is OK, move to next data and sequence
                else:
                    #print("Client: got ok packet")
                    seq_num ^= 1
                    read_data = img.read(self.data_size)
                    # pack
                    send_pkt = Packet(seq_num=seq_num, data=read_data)
                    packed = send_pkt.pkt_pack()
Пример #4
0
    def est_connection(self, syn_pkt: Packet):
        self.client_port = syn_pkt.src
        my_syn = Packet(self.server_port, self.client_port, 0,
                        syn_pkt.ack_num + 1, b'',
                        0x12)  # ack bit = 1, syn bit = 1
        packed = my_syn.pkt_pack()
        self.server_socket.sendto(packed, self.client_addr)

        try:
            syn_ack = Packet()
            recv_data = self.server_socket.recv(self.pkt_size)
            syn_ack.pkt_unpack(recv_data)

            if syn_ack.get_ack_bit() and syn_ack.ack_num == 1:
                self.conn_est = True
                print("Server: Connection established")
            else:
                print("Server: Connection failed: bad SYNACK")
        except socket.timeout:
            print("Server: Connection failed: timeout")
Пример #5
0
    def run(self):
        """
        Runs when Client process has started
        """
        print("Client: Started", flush=True)
        ack = Packet()
        ack_data = b''

        request = "download"
        req_pkt = Packet(0, request)
        req_packed = req_pkt.pkt_pack()

        self.client_socket.sendto(req_packed, self.server_addr)

        ack_data = self.client_socket.recv(self.pkt_size)
        ack.pkt_unpack(ack_data)

        self.recv_img(self.img_save_to)

        ack = Packet()
        ack_data = b''
        request = "upload"
        req_pkt = Packet(0, request)
        req_packed = req_pkt.pkt_pack()

        self.client_socket.sendto(req_packed, self.server_addr)

        ack_data = self.client_socket.recv(self.pkt_size)
        ack.pkt_unpack(ack_data)

        self.send_img(self.img_to_send)

        sleep(5)

        ack = Packet()
        ack_data = b''
        request = "exit"
        req_pkt = Packet(0, request)
        req_packed = req_pkt.pkt_pack()

        self.client_socket.sendto(req_packed, self.server_addr)

        ack_data = self.client_socket.recv(self.pkt_size)
        ack.pkt_unpack(ack_data)

        print("Client: Exiting...")
        # close socket when finished
        self.client_socket.close()
Пример #6
0
    def send_img(self, filename):
        """
        Sends the image packet by packet

        Parameters:
          filename - file to send
        """
        recv_data = b''  # bytes for data received
        recv_pkt = Packet()  # init empty packet for received data
        read_data = b''  # byte string data read from file
        seq_num = 0  # init sequence number
        my_timer = Timer()  # Timer thread
        my_timer.set_time(0.05)  # set timer to 50 ms
        my_timer.stop()  # so timer doesn't start counting
        my_timer.start()  # start timer thread

        # open file to be sent
        print("Server: Sending image to client")
        start = time()
        with open(filename, 'rb') as img:
            read_data = img.read(self.data_size)
            # pack
            send_pkt = Packet(seq_num=seq_num, data=read_data)
            packed = send_pkt.pkt_pack()

            # send data until end of file reached
            while read_data:

                if (self.crpt_data_rate > 0 or self.crpt_ack_rate > 0
                        or self.pkt_loss_rate > 0 or self.ack_loss_rate > 0):
                    self.gen_err_flag()

                # corrupt 1 byte of the sent packet
                if self.crpt_data_rate > 0 and self.err_flag <= self.crpt_data_rate:
                    crptpacked = b"".join([packed[0:1023], b"\x00"])
                    self.server_socket.sendto(crptpacked, self.client_addr)
                elif self.pkt_loss_rate > 0 and self.err_flag <= self.pkt_loss_rate:
                    pass  # dont send anything
                else:
                    self.server_socket.sendto(packed, self.client_addr)

                my_timer.restart()
                if self.pkt_loss_rate > 0 and self.err_flag <= self.pkt_loss_rate:
                    while not my_timer.get_exception():
                        sleep(0.0001)
                else:
                    # wait for ACK
                    recv_data = self.server_socket.recv(self.pkt_size)

                if self.ack_loss_rate > 0 and self.err_flag <= self.ack_loss_rate:
                    while not my_timer.get_exception():
                        sleep(0.0001)
                else:
                    my_timer.stop()

                    # corrupt 1 byte of the recived ACK packet
                    if self.crpt_ack_rate > 0 and self.err_flag <= self.crpt_ack_rate:
                        recv_data = b"".join([recv_data[0:1023], b"\x00"])

                    recv_pkt.pkt_unpack(recv_data)

                    # Received NAK or incorrect ACK
                    if recv_pkt.seq_num != seq_num or recv_pkt.csum != recv_pkt.checksum(
                            recv_pkt.seq_num, recv_pkt.data):
                        pass
                    # ACK is OK, move to next data and sequence
                    else:
                        seq_num ^= 1
                        read_data = img.read(self.data_size)
                        # pack
                        send_pkt = Packet(seq_num=seq_num, data=read_data)
                        packed = send_pkt.pkt_pack()

        my_timer.kill()
        my_timer.join()
        end = time()
        print("Server: Time to send image:", end - start)
Пример #7
0
    def run(self):
        """
        Runs when Server process has started
        """
        print("Server: Started")
        i = 0  # index of timeouts

        while True:
            try:
                print("Server: Ready", flush=True)
                # get request and address from client
                msg = b''  # set message to empty string
                recv_data = b''  # set received data to empty string
                msg_pkt = Packet()  # init empty packet
                (recv_data,
                 self.client_addr) = self.server_socket.recvfrom(self.pkt_size)
                i = 0  # reset timeout index
                #print("got data")
                msg_pkt.pkt_unpack(recv_data)
                #print("Received message:", msg_pkt)

                if msg_pkt.csum != msg_pkt.checksum(msg_pkt.seq_num,
                                                    msg_pkt.data):
                    # send NAK
                    nak_seq = msg_pkt.seq_num ^ 0x01
                    ack = Packet(nak_seq, "ACK")
                    ack_pack = ack.pkt_pack()
                    self.server_socket.sendto(ack_pack, self.client_addr)
                else:
                    msg = msg_pkt.data.decode()
                    print("Server: Client request:", msg, flush=True)

            except socket.timeout:
                i = i + 1
                if (i < 6):
                    pass
                # if the server has waited through 6 timeouts (12 seconds), exit
                else:
                    print("Server: I'm tired of waiting", flush=True)
                    break

            # if any message recieved, then service it
            if msg:
                # ------------------ Send image to client ------------------
                if msg == "download":
                    print("Server: Send ACK")
                    ack = Packet(msg_pkt.seq_num, "ACK")
                    #print("ACK:", ack)
                    ack_pack = ack.pkt_pack()
                    #print(int.from_bytes(ack_pack[(len(ack_pack)-2):len(ack_pack)], byteorder='big', signed=False))
                    self.server_socket.sendto(ack_pack, self.client_addr)

                    # break
                    self.send_img(self.img_to_send)

                # ------------------ Get image from client ------------------
                elif msg == "upload":
                    print("Server: Send ACK")
                    ack = Packet(msg_pkt.seq_num, "ACK")
                    ack_pack = ack.pkt_pack()
                    self.server_socket.sendto(ack_pack, self.client_addr)

                    self.recv_img(self.img_save_to)

                # ------------------ Exit server process ------------------
                elif msg == "exit":
                    print("Server: Send ACK")
                    ack = Packet(msg_pkt.seq_num, "ACK")
                    ack_pack = ack.pkt_pack()
                    self.server_socket.sendto(ack_pack, self.client_addr)

                    print("Server: Exiting...")
                    break

                # ------------------ Handle invalid request ------------------
                else:
                    # send NAK
                    nak_seq = msg_pkt.seq_num ^ 0x01
                    ack = Packet(nak_seq, "ACK")
                    ack_pack = ack.pkt_pack()
                    self.server_socket.sendto(ack_pack, self.client_addr)

                    print("Server: Received invalid request:", msg)

        # close socket when finished
        self.server_socket.close()
Пример #8
0
    def send_img(self, filename):
        """
        Sends the image packet by packet

        Parameters:
          filename - file to send
        """
        recv_data = b''  # bytes for data received
        recv_pkt = Packet()  # init empty packet for received data
        read_data = b''  # byte string data read from file
        seq_num = 0  # init sequence number
        base = 0  # init base packet number
        window = []  # init window as empty list
        win_idx = 0  # index to item in window
        last_sent = None
        my_timer = Timer()  # Timer thread
        my_timer.set_time(0.1)  # set timer to 100 ms
        my_timer.stop()  # so timer doesn't start counting
        my_timer.start()  # start timer thread

        self.client_socket.settimeout(0)  # don't block when waiting for ACKs

        # open file to be sent
        print("Client: Sending image to server")
        # start = time()
        with open(filename, 'rb') as img:
            read_data = img.read(self.data_size)
            # pack
            send_pkt = Packet(seq_num=seq_num, data=read_data)
            packed = send_pkt.pkt_pack()

            # add first packet to window list
            window.append(packed)

            # send data until end of file reached
            while read_data or len(window) > 0:
                if my_timer.get_exception():
                    self.resend_window(window)
                    my_timer.restart()

                win_idx = len(window) - 1
                if seq_num < (base + self.N) and window[win_idx] != last_sent:
                    self.client_socket.sendto(window[win_idx],
                                              self.server_addr)
                    last_sent = window[win_idx]
                    if base == seq_num:
                        my_timer.restart()  # start timer
                    seq_num += 1

                # wait for ACK
                if recv_data:
                    recv_data = b''  # empty data buffer
                try:
                    recv_data = self.client_socket.recv(self.pkt_size)
                except socket.error as e:
                    if e == 10035:
                        pass

                if recv_data:
                    recv_pkt.pkt_unpack(recv_data)

                    # Received NAK
                    if recv_pkt.csum != recv_pkt.checksum(
                            recv_pkt.seq_num, recv_pkt.data):
                        pass
                    # ACK is OK
                    else:
                        base = recv_pkt.seq_num + 1  # increment base
                        window.pop(0)  # remove acked packet from window
                        if base == seq_num:
                            my_timer.stop()
                        else:
                            my_timer.restart()
                # Move to next data
                if len(window) < self.N and read_data:
                    read_data = img.read(self.data_size)
                    # pack
                    send_pkt = Packet(seq_num=seq_num, data=read_data)
                    packed = send_pkt.pkt_pack()
                    window.append(packed)  # add packet to window
                sleep(0.0001)

        # end = time()
        my_timer.kill()
        my_timer.join()
        self.client_socket.settimeout(5)  # reset timeout value
Пример #9
0
    def send_img(self, filename):
        """
    Sends the image packet by packet

    Parameters:
      filename - file to send
    """
        recv_data = b''  # bytes for data received
        recv_pkt = Packet()  # init empty packet for received data
        read_data = b''  # byte string data read from file
        seq_num = 0  # init sequence number
        snd_crpt_rate = 0  # packet corruption rate in percent
        crpt_flag = 1  # corruption flag
        snd_ackcrpt_rate = 0  # recived ACK corruption rate inpercent
        ackcrpt_flag = 1  # corruption flag for ACK

        # open file to be sent
        print("Server: Sending image to client")
        # start = time()
        with open(filename, 'rb') as img:
            read_data = img.read(self.data_size)

            # send data until end of file reached
            while read_data:
                # pack and send
                send_pkt = Packet(seq_num=seq_num, data=read_data)
                packed = send_pkt.pkt_pack()

                # Iteration to corrupt 2 bytes of the sent packet
                if crpt_flag <= snd_crpt_rate:
                    crptpacked = b"".join([packed[0:1023], b"\x00"])
                    self.server_socket.sendto(crptpacked, self.client_addr)
                    crpt_flag = crpt_flag + 1
                else:
                    crpt_flag = crpt_flag + 1
                    self.server_socket.sendto(packed, self.client_addr)
                if crpt_flag > 100:
                    crpt_flag = 1

                # wait for ACK
                recv_data = self.server_socket.recv(self.pkt_size)

                # Iteration to corrupt 2 bytes of the recived ACK packet
                if ackcrpt_flag <= snd_ackcrpt_rate:
                    recv_data = b"".join([recv_data[0:1023], b"\x00"])
                    ackcrpt_flag = ackcrpt_flag + 1
                else:
                    ackcrpt_flag = ackcrpt_flag + 1
                if ackcrpt_flag > 100:
                    ackcrpt_flag = 1

                recv_pkt.pkt_unpack(recv_data)

                # Received NAK or incorrect ACK
                if recv_pkt.seq_num != seq_num or recv_pkt.csum != recv_pkt.checksum(
                        recv_pkt.seq_num, recv_pkt.data):
                    pass
                # ACK is OK, move to next data and sequence
                else:
                    seq_num ^= 1
                    read_data = img.read(self.data_size)
Пример #10
0
    def run(self):
        """
        Runs when Client process has started
        """
        print("Client: Started", flush=True)
        ack = Packet()
        ack_data = b''

        self.est_connection()

        request = "download"
        req_pkt = Packet(src=self.client_port,
                         dst=self.server_port,
                         seq_num=0,
                         ack_num=0,
                         data=request,
                         ctrl_bits=0x00)
        req_packed = req_pkt.pkt_pack()

        self.client_socket.sendto(req_packed, self.server_addr)

        ack_data = self.client_socket.recv(self.pkt_size)
        ack.pkt_unpack(ack_data)

        self.recv_img(self.img_save_to)
        """ ack = Packet()
        ack_data = b''
        request = "upload"
        req_pkt = Packet(src=self.client_port,
                         dst=self.server_port,
                         seq_num=0,
                         ack_num=0,
                         data=request,
                         ctrl_bits=0x00)
        req_packed = req_pkt.pkt_pack()

        self.client_socket.sendto(req_packed, self.server_addr)

        ack_data = self.client_socket.recv(self.pkt_size)
        ack.pkt_unpack(ack_data)

        self.send_img(self.img_to_send)

        sleep(5) """

        ack = Packet()
        ack_data = b''
        request = "exit"
        req_pkt = Packet(src=self.client_port,
                         dst=self.server_port,
                         seq_num=0,
                         ack_num=0,
                         data=request,
                         ctrl_bits=0x01)
        req_packed = req_pkt.pkt_pack()

        self.client_socket.sendto(req_packed, self.server_addr)

        ack_data = self.client_socket.recv(self.pkt_size)
        ack.pkt_unpack(ack_data)
        fin = Packet()
        fin_data = self.client_socket.recv(self.pkt_size)
        fin.pkt_unpack(fin_data)

        ack = Packet(src=self.client_port,
                     dst=self.server_port,
                     seq_num=0,
                     ack_num=0,
                     data=b'',
                     ctrl_bits=0x10)

        ack_pack = ack.pkt_pack()
        self.client_socket.sendto(ack_pack, self.server_addr)
        print("Client: Connection closed")

        print("Client: Exiting...")
        # close socket when finished
        self.client_socket.close()
Пример #11
0
    def recv_img(self, filename):
        """
        Receive an image packet by packet
        Saves image to specified file

        Parameters:
          filename - file location to save image
        """
        recv_data = b''  # packet of byte string data
        save_data = b''  # data to be saved to file
        img_not_recvd = True  # flag to indicate if image data hasn't started yet
        exp_seq = 0  # expected sequence number initially 0
        chunks = {}  # init dictionary of received data chunks
        pkt = Packet()

        # get image data from server until all data received
        while True:
            try:
                if (self.crpt_ack_rate > 0 or self.ack_loss_rate > 0):
                    self.gen_err_flag()

                if img_not_recvd:
                    print("Client: Ready to receive image", flush=True)

                recv_data = self.client_socket.recv(self.pkt_size)

                pkt.pkt_unpack(recv_data)
                if pkt.seq_num < exp_seq or pkt.csum != pkt.checksum():
                    pass
                elif pkt.seq_num > exp_seq:
                    if pkt.seq_num not in chunks.keys():
                        chunks[pkt.seq_num] = pkt.data
                else:
                    chunks[pkt.seq_num] = pkt.data
                    # increment expected sequence to highest received data
                    exp_seq += len(pkt.data)
                    while exp_seq in chunks.keys():
                        exp_seq += len(chunks[exp_seq])

                ack = Packet(src=self.client_port,
                             dst=self.server_port,
                             seq_num=0,
                             ack_num=exp_seq,
                             data=b'',
                             ctrl_bits=0x10)

                ack_pack = ack.pkt_pack()

                if (self.ack_loss_rate > 0
                        and self.err_flag <= self.ack_loss_rate):
                    pass
                elif (self.crpt_ack_rate > 0
                      and self.err_flag <= self.crpt_ack_rate):
                    ack_pack = b"".join([ack_pack[0:1023], b"\x01"])
                    self.client_socket.sendto(ack_pack, self.server_addr)
                else:
                    self.client_socket.sendto(ack_pack, self.server_addr)

                if img_not_recvd:
                    img_not_recvd = False  # img data began streaming if it reaches this point

            except socket.timeout:
                # if image not recieved yet, keep waiting
                if img_not_recvd:
                    pass
                # image has been recieved
                else:
                    break  # exit loop

        for chunk in sorted(chunks.keys()):
            save_data += chunks[chunk]
        # write data into a file
        with open(filename, 'wb+') as client_img:
            client_img.write(save_data)
        print("Client: Received and saved image", flush=True)
Пример #12
0
    def send_img(self, filename):
        """
        Sends the image packet by packet

        Parameters:
          filename - file to send
        """
        recv_data = b''  # bytes for data received
        recv_pkt = Packet()  # init empty packet for received data
        read_data = b''  # byte string data read from file
        seq_num = 0  # init sequence number
        base = 0  # init base packet number
        window = {}  # init window as empty dict
        dupl_cnt = 0  # count of duplicate acks
        my_timer = Timer()  # Timer thread
        my_timer.set_time(0.1)  # set timer to 100 ms
        my_timer.stop()  # so timer doesn't start counting
        my_timer.start()  # start timer thread
        rtt_start = {}

        self.client_socket.settimeout(0)  # don't block when waiting for ACKs

        # open file to be sent
        print("Client: Sending image to server")
        # start = time()
        with open(filename, 'rb') as img:
            read_data = img.read(self.data_size)
            # pack
            send_pkt = Packet(src=self.client_port,
                              dst=self.server_port,
                              seq_num=seq_num,
                              ack_num=0,
                              data=read_data,
                              ctrl_bits=0x00)
            next_pkt = send_pkt.pkt_pack()

            # add first packet to window list
            window[send_pkt.seq_num] = next_pkt

            # send data until all data acked
            while read_data or len(window) > 0:
                # Move to next data
                if len(window) < self.N and read_data:
                    read_data = img.read(self.data_size)
                    # pack
                    if read_data:
                        send_pkt = Packet(src=self.client_port,
                                          dst=self.server_port,
                                          seq_num=seq_num,
                                          ack_num=0,
                                          data=read_data,
                                          ctrl_bits=0x00)
                        next_pkt = send_pkt.pkt_pack()
                        window[send_pkt.
                               seq_num] = next_pkt  # add packet to window
                    else:  # no more data to be sent
                        next_pkt = None

                if next_pkt:
                    self.client_socket.sendto(next_pkt, self.server_addr)
                    next_pkt = None
                    rtt_start[send_pkt.seq_num] = time()
                    if base == seq_num:
                        my_timer.restart()  # start timer
                    seq_num += len(send_pkt.data)

                if my_timer.get_exception():
                    self.N = ceil(self.N / 2)
                    self.resend_lost(window, base)
                    rtt_start[base] = time()
                    my_timer.restart()

                # receive ACK
                if recv_data:
                    recv_data = b''  # empty data buffer
                try:
                    recv_data = self.client_socket.recv(self.pkt_size)
                except socket.error as e:
                    if e == 10035:
                        pass

                if recv_data:
                    recv_pkt.pkt_unpack(recv_data)

                    if recv_pkt.csum != recv_pkt.checksum():
                        pass
                    # ACK is OK
                    else:
                        rtt_end = time()
                        if recv_pkt.ack_num > base:
                            dupl_cnt = 0  # reset duplicate count
                            prev_base = base
                            base = recv_pkt.ack_num  # increment base
                            for pkt in sorted(window.keys(
                            )):  # remove acked packets from window
                                if pkt < base:
                                    window.pop(pkt)
                                else:
                                    break
                            if len(window) == 0:  # no unacked packets
                                my_timer.stop()
                            else:  # unacked packets remaining
                                my_timer.restart(
                                    self.est_timeout(rtt_end -
                                                     rtt_start[prev_base]))
                            self.N += 1
                        elif recv_pkt.ack_num == base:
                            dupl_cnt += 1
                        # received 3 duplicate ACKs
                        if dupl_cnt >= 3:
                            dupl_cnt = 0
                            self.N = ceil(self.N / 2)
                            self.resend_lost(window, base)
                            rtt_start[base] = time()
                            my_timer.restart()

                sleep(0.0001)

        # end = time()
        my_timer.kill()
        my_timer.join()
        self.N = 1  #reset window size
        self.est_rtt = 0.1  # reset estimated rtt
        self.dev_rtt = 0  # reset deviation
        self.client_socket.settimeout(1)  # reset timeout value
Пример #13
0
    def send_img(self, filename):
        """
        Sends the image packet by packet

        Parameters:
          filename - file to send
        """
        recv_data = b''  # bytes for data received
        recv_pkt = Packet()  # init empty packet for received data
        read_data = b''  # byte string data read from file
        seq_num = 0  # init sequence number
        base = 0  # init base packet number
        window = {}  # init window as empty dictionary
        dupl_cnt = 0  # count of duplicate acks
        my_timer = Timer()  # Timer thread
        my_timer.set_time(0.1)  # set timer to 100 ms
        my_timer.stop()  # so timer doesn't start counting
        my_timer.start()  # start timer thread
        rtt_start = {}
        window_list = []
        rtt_list = []
        new_timeout = 0.1

        self.server_socket.settimeout(0)  # don't block when waiting for ACKs

        # open file to be sent
        print("Server: Sending image to client")
        start = time()
        with open(filename, 'rb') as img:
            read_data = img.read(self.data_size)
            # pack
            send_pkt = Packet(src=self.server_port,
                              dst=self.client_port,
                              seq_num=seq_num,
                              ack_num=0,
                              data=read_data,
                              ctrl_bits=0x00)
            next_pkt = send_pkt.pkt_pack()

            # add first packet to window list
            window[send_pkt.seq_num] = next_pkt

            # send data until all data acked
            while read_data or len(window) > 0:
                if (self.crpt_data_rate > 0 or self.pkt_loss_rate > 0):
                    self.gen_err_flag()

                window_list.append(self.N)
                rtt_list.append(new_timeout)

                # Move to next data
                if len(window) < self.N and read_data:
                    read_data = img.read(self.data_size)
                    # pack
                    if read_data:
                        send_pkt = Packet(src=self.server_port,
                                          dst=self.client_port,
                                          seq_num=seq_num,
                                          ack_num=0,
                                          data=read_data,
                                          ctrl_bits=0x00)
                        next_pkt = send_pkt.pkt_pack()
                        window[send_pkt.
                               seq_num] = next_pkt  # add packet to window
                    else:  # no more data to be sent
                        next_pkt = None

                if next_pkt:
                    if self.crpt_data_rate > 0 and self.err_flag <= self.crpt_data_rate:
                        # corrupt 1 byte of the sent packet
                        crptpacked = b"".join([next_pkt[0:1023], b"\x00"])
                        self.server_socket.sendto(crptpacked, self.client_addr)
                    elif self.pkt_loss_rate > 0 and self.err_flag <= self.pkt_loss_rate:
                        pass  # dont send anything
                    else:
                        # send normally
                        self.server_socket.sendto(next_pkt, self.client_addr)
                    next_pkt = None
                    rtt_start[send_pkt.seq_num] = time()
                    if base == seq_num:
                        my_timer.restart()  # start timer
                    seq_num += len(send_pkt.data)

                if my_timer.get_exception():
                    self.N = ceil(self.N / 2)
                    self.resend_lost(window, base)
                    rtt_start[base] = time()
                    my_timer.restart()

                # receive ACK
                if recv_data:
                    recv_data = b''  # empty data buffer
                try:
                    recv_data = self.server_socket.recv(self.pkt_size)
                except socket.error as e:
                    if e == 10035:
                        pass

                if recv_data:
                    recv_pkt.pkt_unpack(recv_data)

                    # Received NAK
                    if recv_pkt.csum != recv_pkt.checksum():
                        pass
                    # ACK is OK
                    else:
                        rtt_end = time()
                        if recv_pkt.ack_num > base:
                            dupl_cnt = 0  # reset duplicate count
                            prev_base = base
                            base = recv_pkt.ack_num  # increment base
                            for pkt in sorted(window.keys(
                            )):  # remove acked packets from window
                                if pkt < base:
                                    window.pop(pkt)
                                else:
                                    break
                            if len(window) == 0:  # no unacked packets
                                my_timer.stop()
                            else:  # unacked packets remaining
                                new_timeout = rtt_end - rtt_start[prev_base]
                                my_timer.restart(self.est_timeout(new_timeout))

                            self.N += 1

                        elif recv_pkt.ack_num == base:
                            dupl_cnt += 1
                        # received 3 duplicate ACKs
                        if dupl_cnt >= 3:
                            dupl_cnt = 0
                            self.N = ceil(self.N / 2)
                            self.resend_lost(window, base)
                            rtt_start[base] = time()
                            my_timer.restart()

                sleep(0.0001)

        end = time()
        my_timer.kill()
        my_timer.join()

        with open("window_size.csv", 'w+', newline='') as win_csv:
            writer = csv.writer(win_csv, delimiter=',')
            writer.writerow(window_list)

        with open("rtt_times.csv", 'w+', newline='') as rtt_csv:
            writer = csv.writer(rtt_csv, delimiter=',')
            writer.writerow(rtt_list)

        self.N = 1  #reset window size
        self.est_rtt = 0.1  # reset estimated rtt
        self.dev_rtt = 0  # reset deviation
        self.server_socket.settimeout(5)  # reset timeout value
        print("Server: Time to send image:", end - start)
Пример #14
0
    def run(self):
        """
        Runs when Server process has started
        """
        print("Server: Started")
        i = 0  # index of timeouts

        while True:
            try:
                print("Server: Ready", flush=True)
                # get request and address from client
                msg = b''  # set message to empty string
                recv_data = b''  # set received data to empty string
                msg_pkt = Packet()  # init empty packet
                (recv_data,
                 self.client_addr) = self.server_socket.recvfrom(self.pkt_size)
                i = 0  # reset timeout index
                msg_pkt.pkt_unpack(recv_data)

                if msg_pkt.get_syn_bit():
                    print("Server: Client request: Pls let me connect",
                          flush=True)
                else:
                    msg = msg_pkt.data.decode()
                    print("Server: Client request:", msg, flush=True)

            except socket.timeout:
                i = i + 1
                if (i < 6):
                    pass
                # if the server has waited through 6 timeouts (30 seconds), exit
                else:
                    print("Server: I'm tired of waiting", flush=True)
                    break
            if self.conn_est:
                # if any message recieved, then service it
                # ------------------ Send image to client ------------------
                if msg == "download":
                    ack = Packet(self.server_port, self.client_port, 0,
                                 msg_pkt.ack_num + 1, b'', 0x10)
                    ack_pack = ack.pkt_pack()
                    self.server_socket.sendto(ack_pack, self.client_addr)

                    # break
                    self.send_img(self.img_to_send)

                # ------------------ Get image from client ------------------
                elif msg == "upload":
                    ack = Packet(self.server_port, self.client_port, 0,
                                 msg_pkt.ack_num + 1, b'', 0x10)
                    ack_pack = ack.pkt_pack()
                    self.server_socket.sendto(ack_pack, self.client_addr)

                    self.recv_img(self.img_save_to)

                # ------------------ Exit server process ------------------
                elif msg == "exit":
                    ack = Packet(self.server_port, self.client_port, 0,
                                 msg_pkt.ack_num + 1, b'', 0x10)
                    ack_pack = ack.pkt_pack()
                    self.server_socket.sendto(ack_pack, self.client_addr)
                    # send FIN packet
                    fin = Packet(self.server_port, self.client_port, 0, 0, b'',
                                 0x01)
                    fin_pack = fin.pkt_pack()
                    self.server_socket.sendto(fin_pack, self.client_addr)

                    fin_ack = Packet()
                    recv_data = self.server_socket.recv(self.pkt_size)
                    fin_ack.pkt_unpack(recv_data)

                    if fin_ack.get_ack_bit:
                        print("Server: Connection closed")
                        print("Server: Exiting...")
                        break
                    else:
                        print("Server: Connection teardown failed")

                # ------------------ Handle invalid request ------------------
                else:
                    # send NAK
                    ack = Packet(self.server_port, self.client_port, 0, 0, b'',
                                 0x10)
                    ack_pack = ack.pkt_pack()
                    self.server_socket.sendto(ack_pack, self.client_addr)

                    print("Server: Received invalid request:", msg_pkt)
                    # break
            elif msg_pkt.get_syn_bit and not self.conn_est:
                print("Server: Establishing Connection...")
                self.est_connection(msg_pkt)
            else:
                print("Server: Connection not established yet")
                # send NAK
                ack = Packet(self.server_port, self.client_port, 0, 0, b'',
                             0x10)
                ack_pack = ack.pkt_pack()
                self.server_socket.sendto(ack_pack, self.client_addr)

        # close socket when finished
        self.server_socket.close()