Пример #1
0
 def __init__(self, port: int, host: str):
     """initialize sender (client)
     
     Arguments:
         port {int} -- port number of the server(receiver)
         host {str} -- hostnamse of the server
     """
     Rudp.__init__(self, port, host)
     self.server = (self.host, self.port)
     self.socket.settimeout(RudpSender.timeout)
Пример #2
0
    def goBackNSend(self, f):
        """GBN file sending method
        
        Arguments:
            f {file} -- (opened) readable binary file
        """
        size = Rudp.getFileSize(f)
        log.info("File Size: " + str(size))

        self.stopAndWaitSendData(Rudp.signature.encode())
        self.stopAndWaitSendData(str(size).encode())

        # a list holding on-flight packets
        sendList = []
        # indicates the end of file
        readEnd = False
        # store recent acks for congestion control
        ackList = []

        while (not readEnd) or (len(sendList)):
            # fill sendList
            packetToFill = RudpSender.sendWindow - len(sendList)
            if packetToFill > 0:
                for i in range(packetToFill):
                    data = self.__readNext(f)
                    if data:
                        p = self.send(data)
                        print("Packet Seq: ", p.seq, " Added to Send List")
                        sendList.append(p)
                    else:
                        readEnd = True
            # try to receive ack
            try:
                while len(sendList):
                    ack = self.acknowledge()
                    print("Ack Received: ", ack)
                    self.mark(sendList, ack)
                    ackList.append(ack)
                    self.checkDupAcks(ackList)
                    sendList = Rudp.cleanPacketList(sendList)
            except socket.timeout:
                print("Timeout")
                self.resendPackets(sendList)
                if RudpSender.enableCongestionControl:
                    self.congestionControl(RudpSender.LossEvent.Timeout)
            except RudpSender.DupAcks:
                print("Dupacks")
                ackList = []
                self.resendPackets(sendList)
                if RudpSender.enableCongestionControl:
                    self.congestionControl(RudpSender.LossEvent.DupAcks)
            else:
                if RudpSender.enableCongestionControl:
                    self.congestionControl(RudpSender.LossEvent.NoLoss)
Пример #3
0
    def recvData(self) -> bytes:
        """receive from socket and return the content and acknowledge the packet
        used in stop and wait
        
        Returns:
            bytes -- Rudp.Packet.payload
        """

        packet = self.recvPacket()
        if (packet.seq == Rudp.ackPlusOne(self.ack)):
            self.ack = Rudp.ackPlusOne(self.ack)
            self.acknowledgePacket(packet)
            return packet.payload
        else:
            return None
Пример #4
0
 def acknowledge(self, sequence: int):
     """send packet acknowledging a sequence number to the client
     
     Arguments:
         sequence {int} -- sequence #
     """
     ackPacket = Rudp.Packet(self.seq, sequence)
     frame = ackPacket.construct()
     self.seqPlusOne()
     self.socket.sendto(frame, self.client)
Пример #5
0
 def __init__(self, port: int):
     """initialize receiver
     
     Arguments:
         port {int} -- port number to bind on local server
     """
     Rudp.__init__(self, p=port)
     self.client = None
     self.ack = None
     # for testing on server
     self.host = "10.10.2.10"
     # for local test
     # self.host = "127.0.0.1"
     # host = socket.gethostname()
     # self.host = socket.gethostbyname(host)
     try:
         print(self.host, self.port)
         self.socket.bind((self.host, self.port))
     except Exception as e:
         print("Cannot bind port: ", self.port, ". Because:", format(e))
Пример #6
0
 def send(self, data: bytes):
     """warp a packet for data and send this
     
     Arguments:
         data {bytes} -- data to send
     """
     packet = Rudp.Packet(self.seq, 0, data)
     packet.timesamp = time()
     self.sendPacket(packet)
     self.seqPlusOne()
     return (packet)
Пример #7
0
    def goBackNRecv(self, f):
        """GBN file receiving method
        
        Arguments:
            f {_io.TextIOWrapper} -- (opened) file to write
        """
        self.listen()
        size = self.getSize()

        # cache for incoming packets
        recvList = []

        while True:
            try:
                recvPacket = self.recvPacket()
                print("Packet Seq: ", recvPacket.seq, " Received")
                recvList = self.insertOrderedPacket(recvPacket, recvList)
            except (Rudp.InvalidPacket, Rudp.WrongClient):
                pass
            # ack consecutive packets and write to file
            for packet in recvList:
                if packet.seq == Rudp.ackPlusOne(self.ack):
                    self.acknowledge(packet.seq)
                    self.ack = Rudp.ackPlusOne(self.ack)
                    f.write(packet.payload)
                    f.flush()
                    packet.status = False
                    print("Packet Seq: ", packet.seq, " Acked and Written")
                else:
                    self.acknowledge(self.ack)
            if not len(recvList):
                self.acknowledge(self.ack)

            # drop acked files
            self.cleanPacketList(recvList)

            if Rudp.getFileSize(f) == size:
                f.close()
                log.info("Transmission Complete, exit...")
                break
Пример #8
0
    def stopAndWaitRecv(self, f):
        """stop-and-wait file receiving method
        
        Arguments:
            f {_io.TextIOWrapper} -- (opened) file to save
        """
        self.listen()
        size = self.getSize()

        while True:
            try:
                data = self.recvData()
            except Exception as e:
                print(format(e))
            if data:
                f.write(data)
                f.flush()
                print("file size: ", Rudp.getFileSize(f))
            if Rudp.getFileSize(f) == size:
                f.close()
                log.info("Transmission Complete, exit...")
                break
Пример #9
0
 def recvPacket(self) -> Rudp.Packet:
     """receive a valid packet from the client
     
     Raises:
         Rudp.WrongClient: the address of the client doesn't corresponds to self.client
     
     Returns:
         Rudp.Packet -- received packet
     """
     (packet, validity, c) = self.recv()
     if (c != self.client):
         raise Rudp.WrongClient("Wrong Package from " + c)
     return packet
Пример #10
0
    def recv(self) -> tuple:
        """receive raw data from socket and check the validity by checksum
        
        Raises:
            Rudp.InvalidPacket: checksum doesn't match the packet's data
        
        Returns:
            tuple -- (Rudp.Packet, validity: bool, client:(ip addr, port))
        """
        (data, c) = self.socket.recvfrom(Rudp.Packet.buffer())
        # print(data)
        (packet, validity) = Rudp.Packet.unpack(data)
        if (validity):
            print("Valid Packet Received From: ", c)
        else:
            raise Rudp.InvalidPacket("Invalid Packet Received")

        return (packet, validity, c)
Пример #11
0
    def stopAndWaitSend(self, f):
        """stop-and-wait file sending method 
        
        Arguments:
            f {file} -- (opened) readable binary file to send
        """
        size = Rudp.getFileSize(f)
        log.info("File Size: " + str(size))

        self.stopAndWaitSendData(Rudp.signature.encode())
        self.stopAndWaitSendData(str(size).encode())

        while True:
            data = self.__readNext(f)
            if data:
                self.stopAndWaitSendData(data)
            else:
                break
Пример #12
0
 def cleanPacketList(self, packets: list) -> list:
     result = Rudp.cleanPacketList(packets)
     for p in result:
         if p.seq <= self.ack:
             result.remove(p)
     return result