lab3完成代码部分

This commit is contained in:
typingbugs
2024-04-04 20:14:14 +08:00
parent eab9b922b5
commit 2de63a3dc8
2 changed files with 123 additions and 97 deletions

View File

@@ -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()