From 2de63a3dc891e851199945fca4d5c2094d717745 Mon Sep 17 00:00:00 2001 From: typingbugs Date: Thu, 4 Apr 2024 20:14:14 +0800 Subject: [PATCH] =?UTF-8?q?lab3=E5=AE=8C=E6=88=90=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E9=83=A8=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Labs/Lab3/src/Receiver.py | 38 ++++---- Labs/Lab3/src/Sender.py | 182 +++++++++++++++++++++----------------- 2 files changed, 123 insertions(+), 97 deletions(-) diff --git a/Labs/Lab3/src/Receiver.py b/Labs/Lab3/src/Receiver.py index dabe71f..4bdf31f 100755 --- a/Labs/Lab3/src/Receiver.py +++ b/Labs/Lab3/src/Receiver.py @@ -1,18 +1,22 @@ import socket import random -import re +import time class NetworkLayer: - def __init__(self, host="172.29.68.245", port=23666) -> None: + def __init__(self, host:str, port:int) -> None: self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.socket.connect((host, port)) + print("下层的不可靠传输连接成功,等待发送方传输。") def udt_send(self, data:str): self.socket.send(data.encode()) def udt_rcv(self) -> str: - message = self.socket.recv(1024).decode("utf-8") + message = self.socket.recv(12).decode("utf-8") return message + + def close(self): + self.socket.close() class ApplicationLayer: @@ -22,13 +26,13 @@ class ApplicationLayer: class Receiver: def __init__(self, networkLayer:NetworkLayer, applicationLayer:ApplicationLayer): - self.expected_seq_num = 0 + self.expected_seq_num = 1 self.networkLayer = networkLayer self.applicationLayer = applicationLayer def deliver_data(self, data, seq_num): if seq_num == self.expected_seq_num: - print(f'成功收到seq_num={seq_num}, data={data}的包。') + print(f'成功收到seq_num={seq_num}, data=\"{data}\"的包。') self.applicationLayer.data.append(data) self.udt_send(seq_num) self.expected_seq_num += 1 @@ -39,30 +43,28 @@ class Receiver: def udt_send(self, ack_num): print(f"发送ACK={ack_num}", end="") if random.random() > 0.25: - self.networkLayer.socket.send((str(ack_num) + "\n").encode()) + self.networkLayer.socket.send("{:0>4d}".format(ack_num).encode()) else: print(",此包丢失。", end="") print() def extract(self, message:str): - try: - parts = message.split(" ") - seq_num = int(parts[0]) - data = parts[1] - return seq_num, data - except Exception as e: - print(e) - return None, None + seq_num = int(message[:3]) + data = message[4:] + return seq_num, data if __name__ == "__main__": - networkLayer = NetworkLayer() + max_seq_num = 20 + networkLayer = NetworkLayer(host="172.29.68.245", port=23666) applicationLayer = ApplicationLayer() receiver = Receiver(networkLayer, applicationLayer) while True: message = networkLayer.udt_rcv() if message: seq_num, data = receiver.extract(message) - if data: - receiver.deliver_data(data, seq_num) - + receiver.deliver_data(data, seq_num) + if receiver.expected_seq_num == max_seq_num: + break + print("序列传输完成。") + networkLayer.close() diff --git a/Labs/Lab3/src/Sender.py b/Labs/Lab3/src/Sender.py index d11af25..5bfad45 100644 --- a/Labs/Lab3/src/Sender.py +++ b/Labs/Lab3/src/Sender.py @@ -1,32 +1,27 @@ import time import socket import random -import re class Package: def __init__(self, data:str, seq_num:int) -> None: self.data = data self.seq_num = seq_num + self.send_time = None class ApplicationLayer: def __init__(self, data_len:int=5000) -> None: self.data_len = data_len - self.data_to_send = [str(i) + str(i) + str(i) for i in range(data_len)] - self.data_index = 0 - - def get_data(self, query_length) -> list: - data = [(i, self.data_to_send[(self.data_index + i) % self.data_len]) for i in range(query_length)] - self.data_index = (self.data_index + query_length) % self.data_len - return data - + self.data_to_send = ["data{:0>4d}".format(i) for i in range(data_len)] class NetworkLayer: - def __init__(self, host="0.0.0.0", port=23666) -> None: + def __init__(self, host:str, port:int) -> None: self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.socket.bind((host, port)) self.socket.listen(1) + print("等待下层的不可靠传输连接。") self.client_socket, address = self.socket.accept() + print("下层的不可靠传输连接成功。") self.client_socket.setblocking(False) def udt_send(self, data:str): @@ -34,42 +29,63 @@ class NetworkLayer: def udt_rcv(self): try: - return self.client_socket.recv(1024).decode("utf-8") + return self.client_socket.recv(4).decode("utf-8") except BlockingIOError: return None + def close(self): + self.client_socket.close() + self.socket.close() + class Sender: - def __init__(self, window_size:int, timeout_ms:1200, networkLayer:NetworkLayer) -> None: - self.window_size = window_size + 1 - self.window:list[Package] = [None] * self.window_size - self.base_num = 0 - self.next_seq_num = 0 + def __init__( + self, + window_size:int, + max_seq_num:int, + timeout_ms:2000, + networkLayer:NetworkLayer, + ) -> None: + self.window_size = window_size + self.max_seq_num = max_seq_num + self.package_list:list[Package] = [None] * (self.max_seq_num + 1) + self.base_num = 1 + self.next_seq_num = 1 self.timeout_ms = timeout_ms self.networkLayer = networkLayer - self.timer = None + self.timer = False - def rdt_send(self, data:str, seq_num:int) -> bool: - if ((self.next_seq_num + 1) % self.window_size != self.base_num): - self.window[self.next_seq_num] = Package(data, seq_num) - self.udt_send(self.window[self.next_seq_num].data, seq_num) - if (self.next_seq_num == self.base_num): - self.timer = time.time() - self.next_seq_num = (self.next_seq_num + 1) % self.window_size - return True - else: + def rdt_send(self, data:str) -> bool: + if self.next_seq_num > max_seq_num: return False + if self.next_seq_num >= self.base_num + self.window_size: + return False + + self.package_list[self.next_seq_num] = Package(data, self.next_seq_num) + self.udt_send( + self.package_list[self.next_seq_num].data, + self.package_list[self.next_seq_num].seq_num + ) + self.package_list[self.next_seq_num].send_time = time.time() + if self.base_num == self.next_seq_num: + self.timer = True + self.next_seq_num += 1 + return True def rdt_rcv(self, ack_index:int): print(f"收到ACK={ack_index},", end="") - window_index = (ack_index - self.window[self.base_num].seq_num + self.window_size) % self.window_size - self.base_num = (self.base_num + window_index + 1) % self.window_size - print(f"将base_num设置为{self.base_num}。") + if (ack_index < self.base_num): + print(f"(ACK={ack_index}) < (base={self.base_num}),ACK失效丢弃。") + return + self.base_num = ack_index + 1 if self.base_num == self.next_seq_num: - self.timer = None + print(f"将base_num设置为下一个序列编号。") + self.timer = False + else: + print(f"将base_num设置为{self.package_list[self.base_num].seq_num}。") def udt_send(self, data:str, index:int): - index_data = str(index) + ' ' + data + "\n" - print(f"发送data={index_data[:-1]}", end="") + index_data = '{:0>3d} '.format(index) + data + print(f"发送data=\"{index_data}\"", end="") if random.random() > 0.25: self.networkLayer.udt_send(index_data) else: @@ -77,65 +93,73 @@ class Sender: print() def is_timeout(self) -> bool: - if self.timer is None: + if self.timer is False: return False - return time.time() - self.timer >= 0.001 * self.timeout_ms + return time.time() - self.package_list[self.base_num].send_time >= 0.001 * self.timeout_ms def gbn(self): - window_index = self.base_num - while window_index != self.next_seq_num: - self.udt_send(self.window[window_index].data, self.window[window_index].seq_num) - window_index = (window_index + 1) % self.window_size + seq_index = self.base_num + while seq_index < self.next_seq_num: + self.udt_send( + self.package_list[seq_index].data, + self.package_list[seq_index].seq_num + ) + self.package_list[seq_index].send_time = time.time() + seq_index += 1 + + def show_gbn(self) -> list[int]: + show = [] + seq_index = self.base_num + while seq_index < self.next_seq_num: + show.append(self.package_list[seq_index].seq_num) + seq_index += 1 + return show def get_ack_num(self, ack_str:str) -> int: - try: - return int(ack_str.strip()) - except Exception as e: - print(e) - return None + return int(ack_str) if __name__ == "__main__": - networkLayer = NetworkLayer() - applicationLayer = ApplicationLayer() + max_seq_num = 20 + networkLayer = NetworkLayer(host="0.0.0.0", port=23666) + applicationLayer = ApplicationLayer(max_seq_num) sender = Sender( - window_size=50, - timeout_ms=50, + window_size=4, + max_seq_num=max_seq_num, + timeout_ms=2000, networkLayer=networkLayer, ) - while True: - instruct = input() + instruct = input("按回车键开始传输:") + + pkg_list = applicationLayer.data_to_send + index = 1 + while index <= max_seq_num: + time.sleep(1) + data = pkg_list[index - 1] + status = sender.rdt_send(data) + if status: + index += 1 - if instruct == "s": - pkg_list = applicationLayer.get_data(500) - index = 0 - while index != 100: - time.sleep(0.5) - seq_num, data = pkg_list[index] - status = sender.rdt_send(data, seq_num) - if status: - index += 1 + ack_str = networkLayer.udt_rcv() + if ack_str is not None: + ack_num = sender.get_ack_num(ack_str) + sender.rdt_rcv(ack_num) - ack_str = networkLayer.udt_rcv() - if ack_str: - ack_num = sender.get_ack_num(ack_str) - if ack_num is not None: - sender.rdt_rcv(ack_num) + if sender.is_timeout(): + print(f"超时。重传{sender.show_gbn()}") + sender.gbn() - if sender.is_timeout(): - sender.gbn() + while sender.base_num < sender.next_seq_num: + time.sleep(1) + ack_str = networkLayer.udt_rcv() + if ack_str: + ack_num = sender.get_ack_num(ack_str) + if ack_num is not None: + sender.rdt_rcv(ack_num) - while sender.base_num != sender.next_seq_num: - ack_str = networkLayer.udt_rcv() - if ack_str: - ack_num = sender.get_ack_num(ack_str) - if ack_num is not None: - sender.rdt_rcv(ack_num) - - if sender.is_timeout(): - sender.gbn() - - if instruct == "q": - networkLayer.client_socket.close() - networkLayer.socket.close() - exit() + if sender.is_timeout(): + print(f"超时。重传{sender.show_gbn()}") + sender.gbn() + + print("序列传输完成。") + networkLayer.close()