def server_run(self): while True: self.send_data() # 发送数据 readable = select.select([self.socket], [], [], 1)[0] # 非阻塞方法 if len(readable) > 0: # 接收ACK数据 rcv_ack = self.socket.recvfrom( self.ack_buf_size)[0].decode().split()[0] if self.send_base <= int( rcv_ack) < self.next_seq: # 收到ack,则标记为已确认且超时计数为0 print('服务器:收到有用ACK' + rcv_ack) self.ack_seqs[int(rcv_ack)] = True # 设为已接受 if self.send_base == int(rcv_ack): # 收到的ack为最小的窗口序号 self.slide_send_window() # 则滑动窗口 else: print('服务器:收到无用ACK' + rcv_ack) for seq in self.time_counts.keys(): # 每个未接收的分组的时长都加1 if not self.ack_seqs[seq]: # 若未收到ACK self.time_counts[seq] += 1 # 则计次+1 if self.time_counts[seq] > self.time_out: # 触发超时操作 self.handle_time_out(seq) # 超时处理 if self.send_base == len(self.data): # 数据传输结束 self.socket.sendto(Host.make_pkt(0, 0), self.remote_address) # 发送传输结束包 print('服务器:数据传输结束') break
def handle_time_out(self, time_out_seq): print('超时重传:' + str(time_out_seq)) self.time_counts[time_out_seq] = 0 # 重新定时 if random.random() > self.pkt_loss: # 随机发送数据包 self.socket.sendto( Host.make_pkt(time_out_seq, self.data[time_out_seq]), self.remote_address)
def client_run(self): while True: readable = select.select([self.socket], [], [], 1)[0] # 非阻塞接受 if len(readable) > 0: rcv_data = self.socket.recvfrom(self.data_buf_size)[0].decode() rcv_seq = rcv_data.split()[0] # 提取数据包序号 rcv_data = rcv_data.replace(rcv_seq + ' ', '') # 提取数据包数据 if rcv_seq == '0' and rcv_data == '0': # 收到传输数据结束的标志 print('客户端:传输数据结束') break print('客户端:收到数据' + rcv_seq) if self.rcv_base - self.rcv_window_size <= int( rcv_seq) < self.rcv_base + self.rcv_window_size: if self.rcv_base <= int( rcv_seq ) < self.rcv_base + self.rcv_window_size: # 窗口内 self.rcv_data[int( rcv_seq)] = rcv_data # 失序的数据到来:缓存+发送ack if int( rcv_seq ) == self.rcv_base: # 按序数据的到来:滑动窗口并交付数据(清除对应的缓冲区) self.slide_rcv_window() if random.random() >= self.ack_loss: self.socket.sendto(Host.make_pkt(int(rcv_seq), 0), self.remote_address) print('客户端:发送ACK' + rcv_seq)
def handle_time_out(self): print('超时,开始重传') self.time_count = 0 # 超时计次重启 for i in range(self.send_base, self.next_seq): # 发送空中的所有分组 if random.random() > self.pkt_loss: # 概率性重传 self.socket.sendto(Host.make_pkt(i, self.data[i]), self.remote_address) print('数据已重发:' + str(i))
def send_data(self): if self.next_seq == len(self.data): # data数据已全部被发送过 print('服务器:发送完毕,等待确认') return if self.next_seq - self.send_base < self.window_size: # 窗口中仍有可用空间 if random.random() > self.pkt_loss: # 随机产生丢包行为 self.socket.sendto( Host.make_pkt(self.next_seq, self.data[self.next_seq]), self.remote_address) print('服务器:成功发送数据' + str(self.next_seq)) self.next_seq = self.next_seq + 1 else: # 窗口中无可用空间 print('服务器:窗口已满,暂不发送数据')
def send_data(self): if self.next_seq == len(self.data): # 判断是否还有缓存数据可以发送 print('服务器:发送完毕,等待确认') return if self.next_seq < self.send_base + self.send_window_size: # 窗口中仍有可用空间 if random.random() > self.pkt_loss: self.socket.sendto( Host.make_pkt(self.next_seq, self.data[self.next_seq]), self.remote_address) self.time_counts[self.next_seq] = 0 # 设置计时器 self.ack_seqs[self.next_seq] = False # 设置为未接受确认包 print('服务器:发送数据' + str(self.next_seq)) self.next_seq += 1 else: # 窗口中无可用空间 print('服务器:窗口已满,暂不发送数据')
def server_run(self): while True: self.send_data() # 发送数据逻辑 readable = select.select([self.socket], [], [], 1)[0] if len(readable) > 0: # 接收ACK数据 rcv_ack = self.socket.recvfrom( self.ack_buf_size)[0].decode().split()[0] print('收到客户端ACK:' + rcv_ack) self.send_base = int(rcv_ack) + 1 # 滑动窗口的起始序号 self.time_count = 0 # 计时器计次清0 else: # 未收到ACK包 self.time_count += 1 # 超时计次+1 if self.time_count > self.time_out: # 触发超时重传操作 self.handle_time_out() if self.send_base == len(self.data): # 判断数据是否传输结束 self.socket.sendto(Host.make_pkt(0, 0), self.remote_address) # 发送结束报文 print('服务器:发送完毕') break
def client_run(self): while True: readable = select.select([self.socket], [], [], 1)[0] # 非阻塞接收 if len(readable) > 0: # 接收到数据 rcv_data = self.socket.recvfrom(self.data_buf_size)[0].decode() rcv_seq = rcv_data.split()[0] # 按照格式规约获取数据序号 rcv_data = rcv_data.replace(rcv_seq + ' ', '') # 按照格式规约获取数据 if rcv_seq == '0' and rcv_data == '0': # 接收到结束包 print('客户端:传输数据结束') break if int(rcv_seq) == self.exp_seq: # 接收到按序数据包 print('客户端:收到期望序号数据:' + str(rcv_seq)) self.write_data_to_file(rcv_data) # 保存服务器端发送的数据到本地文件中 self.exp_seq = self.exp_seq + 1 # 期望数据的序号更新 else: print('客户端:收到非期望数据,期望:' + str(self.exp_seq) + '实际:' + str(rcv_seq)) if random.random() >= self.ack_loss: # 随机丢包发送数据 self.socket.sendto(Host.make_pkt(self.exp_seq - 1, 0), self.remote_address)