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()
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()
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():
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()
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")
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()