Example #1
0
def replyDownload(s, RcvBuffer, addr):
    # 服务端日志
    logf = open('../log/server-log.txt', mode='w')
    logf.write("Replying Download ")
    print("Replying Download ")

    uniSize = 1024 + 8
    commandformat = '2I'
    ackformat = '2I'
    mss = 1024  #读取字节数
    format = '2I1024s'
    flowCtlrFormat = 'Ii'
    flowCtlrLen = struct.calcsize(flowCtlrFormat)
    receiveSize = 8

    InitialSeqNum = 1
    print("Replying InitialSeqNum ")
    s.sendto(struct.pack(commandformat, 1, InitialSeqNum), addr)

    while True:
        fileInfo, addr = s.recvfrom(1024)

        if len(fileInfo) != 8:
            fileInfo = str(fileInfo, encoding='utf-8')
            print("File Info : ", fileInfo)
            break

    if os.path.exists(fileInfo) == False:
        s.sendto(struct.pack(commandformat, InitialSeqNum, 0), addr)
        print("file requested does not exists")
        return

    print("ACK file exist")
    s.sendto(struct.pack(commandformat, InitialSeqNum, 1), addr)
    s.setblocking(0)

    f = open(fileInfo, mode='rb')

    # 超时重传机制
    TTL = 3
    Timer = 3

    RcvBuffer = 0

    # GBN机制
    Sendbase = InitialSeqNum  # 已发送但未被确认的最小序号
    NextSeqNum = InitialSeqNum  # 下一个要发送的字节序号
    Window = []  # 缓存已发送但未确认的分组
    windowSize = 10  # 窗口大小
    baseIndex = 0
    avaliable = 0

    # 流控制机制
    LastByteSent = 0
    # 最后一个已经发送的字节
    LastByteAcked = 0
    # 最后一个被确认的字节
    rwnd = RcvBuffer

    FileEndFlag = 0
    AllAcked = 0

    # 拥塞控制机制
    cwnd = 1
    ssthresh = 16
    State = 0  # 0:慢启动, 1:拥塞避免
    dupACKcount = 0
    lastACK = 0

    print("Starting file transmition")
    # for i in range(1000):
    while FileEndFlag == 0 or AllAcked == 0:
        #event : data recieved from application : bug not fixed
        if (LastByteSent - LastByteAcked
            ) <= rwnd * mss and (NextSeqNum - Sendbase) / mss < windowSize:

            data = f.read(mss)
            if len(data) < mss:  #补长
                data = data + bytes(mss - len(data))
                FileEndFlag = 1

            Window.append(initPacket(NextSeqNum, data))
            AllAcked = 0

            s.sendto(struct.pack(format, NextSeqNum, 0, data), addr)

            logf.write("sending : " + str(NextSeqNum))
            for x in range(len(Window)):
                logf.write(str(Window[x].seqNum))
            logf.write("\n")

            LastByteSent = NextSeqNum - 1
            NextSeqNum = NextSeqNum + mss

        elif (LastByteSent - LastByteAcked) > rwnd * mss:
            logf.write('\nsending flowCtlr pkt : ' + str(NextSeqNum - mss) +
                       ' rwnd : ' + str(rwnd) + "\n")
            logf.write('LastByteSent : ' + str(LastByteSent) +
                       'LastByteAcked : ' + str(LastByteAcked) + "\n")
            s.sendto(struct.pack(flowCtlrFormat, NextSeqNum - mss, -1), addr)
        # NextSeqNum = NextSeqNum + 1

        #event : ACK received, with field value of y
        reply = 0
        try:
            reply, dstAddr = s.recvfrom(receiveSize)
            ackSeq, rwnd = struct.unpack(ackformat, reply)

            LastByteAcked = ackSeq + mss  # 流控制中,ack seq 不变化

            if lastACK != ackSeq:
                if State == 0:
                    cwnd += 1
                else:
                    cwnd += 1 / cwnd
                dupACKcount = 0
                lastACK = ackSeq
            else:
                duoACKcount += 1

            logf.write("recieve ACK : " + str(ackSeq))
            for x in range(len(Window)):
                logf.write(str(Window[x].seqNum))

            if Sendbase <= ackSeq:  # 累计确认,之前的都是正确确认收到的

                Sendbase = ackSeq + mss
                logf.write("update sendbase : " + str(Sendbase) + "\n")
                while len(Window) != 0:
                    if Window[0].seqNum < Sendbase:
                        del Window[0]
                    else:
                        break
                if Sendbase != NextSeqNum:  #如果当前还有已发送但未被确认的分组: reset timer
                    Timer = 0
                if len(Window) == 0:
                    AllAcked = 1

            # print(reply)
            logf.write("updated Window : ")
            for x in Window:
                logf.write(str(x.seqNum))

        except BlockingIOError:
            pass

        #event : timer out / duoACKcount
        Timer += 1
        if Timer == TTL or dupACKcount == 3:
            State = 0
            ssthresh = cwnd / 2
            cwnd = 1
            duoACKcount = 0
            Timer = 0

            # if Sendbase != NextSeqNum and (LastByteSent-LastByteAcked) <= rwnd*mss:
            if len(
                    Window
            ) != 0:  #retransmit not-ack pkt with smallest seq(Sendbase)(Window[0])?
                logf.write("TIME OUT : retransmit " + str(Window[0].seqNum) +
                           "\n")
                retransmit = struct.pack(format, Window[0].seqNum, 0,
                                         Window[0].data)
                s.sendto(retransmit, addr)

    #挥手
    Timer = 3
    while True:
        print("Starting connection closing")
        FIN = -2
        if Timer == 3:
            s.sendto(struct.pack(flowCtlrFormat, 0, FIN), addr)
            Timer = 0
        Timer += 1
        try:
            reply, addr = s.recvfrom(receiveSize)
            seq, FIN = struct.unpack(commandformat, reply)
            print("Close connection ack recieved")

            while True:
                try:
                    reply, addr = s.recvfrom(receiveSize)
                    print("third wave recieved")
                    break
                except BlockingIOError:
                    pass
            break
        except BlockingIOError:
            pass

    f.close()
    # s.close()
    logf.close()
Example #2
0
def UploadFile(fileLocal, dstAddr):
    logf = open('../log/client-log.txt', mode='w')
    logf.write("Commanding : upload file " + fileLocal + " to " + dstAddr)

    f = open(fileLocal, mode='rb')
    filePath = "D:/"
    fileName, fileFormat = parseFileName(fileLocal)

    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

    InitialSeqNum = 1
    mss = 1024  #读取字节数
    format = '2I1024s'
    ackformat = '2I'
    commandformat = '2I'
    flowCtlrFormat = 'Ii'

    receiveSize = struct.calcsize(ackformat)
    dstIP = dstAddr
    dstPort = 9999

    s.setblocking(0)
    # 超时重传机制
    TTL = 3
    Timer = 3
    RcvBuffer = 0

    # set up connection:
    while True:
        command = 1  #上传命令
        print("sending command ", command, " and initial seqNum ",
              InitialSeqNum)
        if Timer == TTL:
            s.sendto(struct.pack(commandformat, command, InitialSeqNum),
                     (dstIP, dstPort))
            Timer = 0
            TTL *= 2
        Timer += 1
        try:
            print(receiveSize)
            reply, addr = s.recvfrom(receiveSize)
            RcvBuffer, seq = struct.unpack(commandformat, reply)
            print("command pkt ack recieved")

            Timer = 3
            while True:
                if Timer == TTL:
                    print("sending file info")
                    fileInfo = bytes(filePath.encode('utf-8')) + bytes(
                        fileName.encode('utf-8')) + bytes(
                            ("." + fileFormat).encode('utf-8'))
                    s.sendto(fileInfo, (dstIP, dstPort))
                    # s.sendto(bytes(filePath.encode('utf-8')), (dstIP, dstPort))
                Timer += 1
                try:
                    reply, addr = s.recvfrom(receiveSize)
                    print("server : fileInfo recieved ( connection setup")
                    break
                except BlockingIOError:
                    pass
            break
        except BlockingIOError:
            pass

    # GBN机制
    Sendbase = InitialSeqNum  # 已发送但未被确认的最小序号
    NextSeqNum = InitialSeqNum  # 下一个要发送的字节序号
    Window = []  # 缓存已发送但未确认的分组
    windowSize = 10  # 窗口大小

    # 流控制机制
    LastByteSent = 0
    # 最后一个已经发送的字节
    LastByteAcked = 0
    # 最后一个被确认的字节
    rwnd = RcvBuffer

    FileEndFlag = 0
    AllAcked = 0

    # 拥塞控制机制
    cwnd = 1
    ssthresh = 16
    State = 0  # 0:慢启动, 1:拥塞避免
    dupACKcount = 0
    lastACK = 0

    print("Starting file transmition")
    # for i in range(1000):
    while FileEndFlag == 0 or AllAcked == 0:
        #event : data recieved from application : bug not fixed
        if (LastByteSent - LastByteAcked
            ) <= rwnd * mss and (NextSeqNum - Sendbase) / mss < windowSize:

            data = f.read(mss)
            if len(data) < mss:  #补长
                data = data + bytes(mss - len(data))
                FileEndFlag = 1

            Window.append(initPacket(NextSeqNum, data))
            AllAcked = 0

            s.sendto(struct.pack(format, NextSeqNum, 0, data),
                     (dstIP, dstPort))

            logf.write("sending : " + str(NextSeqNum))
            for x in range(len(Window)):
                logf.write(str(Window[x].seqNum))
            logf.write("\n")

            LastByteSent = NextSeqNum - 1
            NextSeqNum = NextSeqNum + mss

        elif (LastByteSent - LastByteAcked) > rwnd * mss:
            logf.write('\nsending flowCtlr pkt : ' + str(NextSeqNum - mss) +
                       ' rwnd : ' + str(rwnd) + "\n")
            logf.write('LastByteSent : ' + str(LastByteSent) +
                       'LastByteAcked : ' + str(LastByteAcked) + "\n")
            s.sendto(struct.pack(flowCtlrFormat, NextSeqNum - mss, -1),
                     (dstIP, dstPort))
            # NextSeqNum = NextSeqNum + 1

        #event : ACK received, with field value of y
        reply = 0
        try:
            reply, dstAddr = s.recvfrom(receiveSize)
            ackSeq, rwnd = struct.unpack(ackformat, reply)

            LastByteAcked = ackSeq + mss  # 流控制中,ack seq 不变化

            if lastACK != ackSeq:
                if State == 0:
                    cwnd += 1
                else:
                    cwnd += 1 / cwnd
                dupACKcount = 0
                lastACK = ackSeq
            else:
                duoACKcount += 1

            logf.write("recieve ACK : " + str(ackSeq))
            for x in range(len(Window)):
                logf.write(str(Window[x].seqNum))

            if Sendbase <= ackSeq:  # 累计确认,之前的都是正确确认收到的

                Sendbase = ackSeq + mss
                logf.write("update sendbase : " + str(Sendbase) + "\n")
                while len(Window) != 0:
                    if Window[0].seqNum < Sendbase:
                        del Window[0]
                    else:
                        break
                if Sendbase != NextSeqNum:  #如果当前还有已发送但未被确认的分组: reset timer
                    Timer = 0
                if len(Window) == 0:
                    AllAcked = 1

            # print(reply)
            logf.write("updated Window : ")
            for x in Window:
                logf.write(str(x.seqNum))

        except BlockingIOError:
            pass

        #event : timer out / duoACKcount
        Timer += 1
        if Timer == TTL or dupACKcount == 3:
            State = 0
            ssthresh = cwnd / 2
            cwnd = 1
            duoACKcount = 0
            Timer = 0

            # if Sendbase != NextSeqNum and (LastByteSent-LastByteAcked) <= rwnd*mss:
            if len(
                    Window
            ) != 0:  #retransmit not-ack pkt with smallest seq(Sendbase)(Window[0])?
                logf.write("TIME OUT : retransmit " + str(Window[0].seqNum) +
                           "\n")
                retransmit = struct.pack(format, Window[0].seqNum, 0,
                                         Window[0].data)
                s.sendto(retransmit, (dstIP, dstPort))

    #挥手
    Timer = 3
    while True:
        print("Starting connection closing")
        FIN = -2
        if Timer == 3:
            s.sendto(struct.pack(flowCtlrFormat, 0, FIN), (dstIP, dstPort))
            Timer = 0
        Timer += 1
        try:
            reply, addr = s.recvfrom(receiveSize)
            seq, FIN = struct.unpack(commandformat, reply)
            print("Close connection ack recieved")

            while True:
                try:
                    reply, addr = s.recvfrom(receiveSize)
                    print("third wave recieved")
                    break
                except BlockingIOError:
                    pass
            break
        except BlockingIOError:
            pass

    f.close()
    s.close()
    logf.close()
Example #3
0
        else:
            logf.write("flow control pkt recieved : " + str(seq) + "\n")
            s.sendto(struct.pack(flowCtlrFormat, seq, rwnd), addr)
            continue

    seq, ack, w = struct.unpack(format, data)
    logf.write("Recieved seq: " + str(seq) + "\n")

    if seq < expSeqNum:  # 丢弃冗余分组
        logf.write("redundant pkt:" + str(seq) + "\n")
        continue

    elif seq > expSeqNum:  # 若缓存仍有空间,缓存乱序到达的pkt
        if not ReceiveBuffer.full() and seq not in bufferedSeq:
            logf.write("put buffer : " + str(seq) + "\n")
            ReceiveBuffer.put(initPacket(seq, w))
            bufferedSeq.append(seq)
            rwnd -= 1
    else:  #seq == expSeqNum:
        ackSeq = seq
        f.write(w)
        expSeqNum += len(w)

        #检查buffer中有无 顺序可写的数据包
        if not ReceiveBuffer.empty():  # buffer不为空
            tmp = ReceiveBuffer.get()  # 取队头元素
            bufferedSeq.remove(tmp.seqNum)

            while tmp.seqNum <= expSeqNum:
                if tmp.seqNum < expSeqNum:  # 若队列中有小于expNum的缓存(冗余),丢弃
                    if ReceiveBuffer.empty():
Example #4
0
def DownloadFile(filePath, dstAddr):

    logf = open('../log/client-log.txt', mode='w')
    logf.write("Commanding : download file " + filePath + " from " + dstAddr)

    uniSize = 1024 + 8
    format = '2I1024s'
    commandformat = '2I'
    ackformat = '2I'
    flowCtlrFormat = 'Ii'
    flowCtlrLen = struct.calcsize(flowCtlrFormat)
    receiveSize = 8

    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    # s.sendto(struct.pack(commandformat, ), )
    dstIP = dstAddr
    dstPort = 9999
    InitialSeqNum = 1
    RcvBufferSize = 20

    s.setblocking(0)
    # set up connection: bug not fixed
    TTL = 3
    Timer = 1
    while True:
        command = 0  #下载命令
        print("sending command ", command, " and initial seqNum ",
              InitialSeqNum)
        if Timer == TTL:
            s.sendto(struct.pack(commandformat, command, RcvBufferSize),
                     (dstIP, dstPort))
            Timer = 0
            TTL *= 2
        Timer += 1
        try:
            # print(s.recvfrom(receiveSize))
            reply, addr = s.recvfrom(receiveSize)
            seq, InitialSeqNum = struct.unpack(commandformat, reply)
            print("command pkt ack recieved")

            Timer = 3
            while True:
                if Timer == TTL:
                    print("sending file info")
                    fileInfo = bytes(filePath.encode('utf-8'))
                    s.sendto(fileInfo, (dstIP, dstPort))
                Timer += 1
                try:
                    reply, addr = s.recvfrom(receiveSize)
                    break
                except BlockingIOError:
                    pass

            break
        except BlockingIOError:
            pass
        except OSError as e:
            print(e)

    seq, fileExist = struct.unpack(commandformat, reply)
    if fileExist == 0:
        print("Server : file requested does not exist")
        s.close()
        logf.write("Server : file requested does not exist")
        logf.close()
        return

    # text, addr = s.recvfrom(struct.calcsize(commandformat))
    # command, expSeqNum = struct.unpack(commandformat, text)
    # print("Received command from ", addr, " command : ", command, " expSeq : ", expSeqNum)

    # RcvBufferSize = 20 # 分配buffer数量
    # s.sendto(struct.pack(commandformat, RcvBufferSize, expSeqNum), addr)

    # 接收文件信息
    # fileInfo, addr = s.recvfrom(1024)
    # f = open(str(fileInfo, encoding = 'utf-8'), mode='wb')
    # print("file info : ", fileInfo)
    # s.sendto(struct.pack(commandformat, RcvBufferSize, expSeqNum), addr)

    # 开始下载文件
    s.setblocking(1)
    fname, fformat = parseFileName(filePath)
    f = open(("D:/testDownload/" + fname + "." + fformat), mode='wb')

    ReceiveBuffer = PriorityQueue(RcvBufferSize)  # 按缓存的seqNum从小到大排列
    bufferedSeq = []
    rwnd = RcvBufferSize  # 缓存可用空间

    expSeqNum = InitialSeqNum
    # for i in range(1000):
    while True:

        data, addr = s.recvfrom(uniSize)

        if len(data) == flowCtlrLen:  # flow control or close connection
            seq, testSeg = struct.unpack(flowCtlrFormat, data)
            if seq == 0 and testSeg == -2:
                print("Close connection pkt recieved")
                break
            else:
                logf.write("flow control pkt recieved : " + str(seq) + "\n")
                s.sendto(struct.pack(flowCtlrFormat, seq, rwnd), addr)
                continue

        seq, ack, w = struct.unpack(format, data)
        logf.write("Recieved seq: " + str(seq) + "\n")

        if seq < expSeqNum:  # 丢弃冗余分组
            logf.write("redundant pkt:" + str(seq) + "\n")
            continue

        elif seq > expSeqNum:  # 若缓存仍有空间,缓存乱序到达的pkt
            if not ReceiveBuffer.full() and seq not in bufferedSeq:
                logf.write("put buffer : " + str(seq) + "\n")
                ReceiveBuffer.put(initPacket(seq, w))
                bufferedSeq.append(seq)
                rwnd -= 1
        else:  #seq == expSeqNum:
            ackSeq = seq
            f.write(w)
            expSeqNum += len(w)

            #检查buffer中有无 顺序可写的数据包
            if not ReceiveBuffer.empty():  # buffer不为空
                tmp = ReceiveBuffer.get()  # 取队头元素
                bufferedSeq.remove(tmp.seqNum)

                while tmp.seqNum <= expSeqNum:
                    if tmp.seqNum < expSeqNum:  # 若队列中有小于expNum的缓存(冗余),丢弃
                        if ReceiveBuffer.empty():
                            break
                        tmp = ReceiveBuffer.get()
                        bufferedSeq.remove(tmp.seqNum)

                    elif expSeqNum == tmp.seqNum:  # 确认并写入磁盘
                        ackSeq = tmp.seqNum
                        f.write(w)
                        expSeqNum += len(tmp.data)

                        if ReceiveBuffer.empty():
                            break
                        tmp = ReceiveBuffer.get()
                        bufferedSeq.remove(tmp.seqNum)

                if expSeqNum < tmp.seqNum:
                    ReceiveBuffer.put(tmp)
                    bufferedSeq.append(tmp.seqNum)

            rwnd = RcvBufferSize - ReceiveBuffer.qsize()
            logf.write("get excepted : " + str(seq) + "update expNum to : " +
                       str(expSeqNum) + "\n")

            # 发送ack
            ackPkt = struct.pack(ackformat, ackSeq, rwnd)
            s.sendto(ackPkt, addr)

    #close connection
    s.sendto(struct.pack(commandformat, seq + 1, 1), addr)

    s.sendto(struct.pack(commandformat, seq + 1, 2), addr)

    s.close()
    f.close()
    logf.close()
Example #5
0
dupACKcount = 0
lastACK = 0

print("Starting file transmition")
# for i in range(1000):
while FileEndFlag == 0 or AllAcked == 0:
    #event : data recieved from application : bug not fixed
    if (LastByteSent - LastByteAcked
        ) <= rwnd * mss and (NextSeqNum - Sendbase) / mss < windowSize:

        data = f.read(mss)
        if len(data) < mss:  #补长
            data = data + bytes(mss - len(data))
            FileEndFlag = 1

        Window.append(initPacket(NextSeqNum, data))
        AllAcked = 0

        s.sendto(struct.pack(format, NextSeqNum, 0, data), (dstIP, dstPort))

        logf.write("sending : " + str(NextSeqNum))
        for x in range(len(Window)):
            logf.write(str(Window[x].seqNum))
        logf.write("\n")

        LastByteSent = NextSeqNum - 1
        NextSeqNum = NextSeqNum + mss

    elif (LastByteSent - LastByteAcked) > rwnd * mss:
        logf.write('\nsending flowCtlr pkt : ' + str(NextSeqNum - mss) +
                   ' rwnd : ' + str(rwnd) + "\n")
Example #6
0
def replyUpload(s, expSeqNum, addr):
    # 服务端日志
    logf = open('../log/server-log.txt', mode='w')
    logf.write("Replying Upload ")

    uniSize = 1024 + 8
    commandformat = '2I'
    ackformat = '2I'
    mss = 1024  #读取字节数
    format = '2I1024s'
    flowCtlrFormat = 'Ii'
    flowCtlrLen = struct.calcsize(flowCtlrFormat)

    RcvBufferSize = 20  # 分配buffer数量
    s.sendto(struct.pack(commandformat, RcvBufferSize, expSeqNum), addr)

    # 接收文件信息
    fileInfo, addr = s.recvfrom(1024)
    f = open(str(fileInfo, encoding='utf-8'), mode='wb')
    print("file info : ", fileInfo)
    s.sendto(struct.pack(commandformat, RcvBufferSize, expSeqNum), addr)

    ReceiveBuffer = PriorityQueue(RcvBufferSize)  # 按缓存的seqNum从小到大排列
    bufferedSeq = []
    rwnd = RcvBufferSize  # 缓存可用空间

    while True:

        data, addr = s.recvfrom(uniSize)

        if len(data) == flowCtlrLen:  # flow control or close connection
            seq, testSeg = struct.unpack(flowCtlrFormat, data)
            if seq == 0 and testSeg == -2:
                print("Close connection pkt recieved")
                break
            else:
                logf.write("flow control pkt recieved : " + str(seq) + "\n")
                s.sendto(struct.pack(flowCtlrFormat, seq, rwnd), addr)
                continue

        seq, ack, w = struct.unpack(format, data)
        logf.write("Recieved seq: " + str(seq) + "\n")

        if seq < expSeqNum:  # 丢弃冗余分组
            logf.write("redundant pkt:" + str(seq) + "\n")
            continue

        elif seq > expSeqNum:  # 若缓存仍有空间,缓存乱序到达的pkt
            if not ReceiveBuffer.full() and seq not in bufferedSeq:
                logf.write("put buffer : " + str(seq) + "\n")
                ReceiveBuffer.put(initPacket(seq, w))
                bufferedSeq.append(seq)
                rwnd -= 1
        else:  #seq == expSeqNum:
            ackSeq = seq
            f.write(w)
            expSeqNum += len(w)

            #检查buffer中有无 顺序可写的数据包
            if not ReceiveBuffer.empty():  # buffer不为空
                tmp = ReceiveBuffer.get()  # 取队头元素
                bufferedSeq.remove(tmp.seqNum)

                while tmp.seqNum <= expSeqNum:
                    if tmp.seqNum < expSeqNum:  # 若队列中有小于expNum的缓存(冗余),丢弃
                        if ReceiveBuffer.empty():
                            break
                        tmp = ReceiveBuffer.get()
                        bufferedSeq.remove(tmp.seqNum)

                    elif expSeqNum == tmp.seqNum:  # 确认并写入磁盘
                        ackSeq = tmp.seqNum
                        f.write(w)
                        expSeqNum += len(tmp.data)

                        if ReceiveBuffer.empty():
                            break
                        tmp = ReceiveBuffer.get()
                        bufferedSeq.remove(tmp.seqNum)

                if expSeqNum < tmp.seqNum:
                    ReceiveBuffer.put(tmp)
                    bufferedSeq.append(tmp.seqNum)

            rwnd = RcvBufferSize - ReceiveBuffer.qsize()
            logf.write("get excepted : " + str(seq) + "update expNum to : " +
                       str(expSeqNum) + "\n")

            # 发送ack
            ackPkt = struct.pack(ackformat, ackSeq, rwnd)
            s.sendto(ackPkt, addr)

    #close connection
    s.sendto(struct.pack(commandformat, seq + 1, 1), addr)

    s.sendto(struct.pack(commandformat, seq + 1, 2), addr)

    # s.close()
    f.close()
    logf.close()