70 lines
2.2 KiB
Python
Executable File
70 lines
2.2 KiB
Python
Executable File
import socket
|
|
import random
|
|
|
|
class NetworkLayer:
|
|
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(12).decode("utf-8")
|
|
return message
|
|
|
|
def close(self):
|
|
self.socket.close()
|
|
|
|
|
|
class ApplicationLayer:
|
|
def __init__(self) -> None:
|
|
self.data = list()
|
|
|
|
|
|
class Receiver:
|
|
def __init__(self, networkLayer:NetworkLayer, applicationLayer:ApplicationLayer):
|
|
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}\"的包。')
|
|
self.applicationLayer.data.append(data)
|
|
self.udt_send(seq_num)
|
|
self.expected_seq_num += 1
|
|
else:
|
|
print(f'收到seq_num={seq_num}, 与预期seq_num={self.expected_seq_num}不符。')
|
|
self.udt_send(self.expected_seq_num - 1)
|
|
|
|
def udt_send(self, ack_num):
|
|
print(f"发送ACK={ack_num}", end="")
|
|
if random.random() > 0.25:
|
|
self.networkLayer.socket.send("{:0>4d}".format(ack_num).encode())
|
|
else:
|
|
print(",此包丢失。", end="")
|
|
print()
|
|
|
|
def extract(self, message:str):
|
|
seq_num = int(message[:3])
|
|
data = message[4:]
|
|
return seq_num, data
|
|
|
|
if __name__ == "__main__":
|
|
max_seq_num = 20
|
|
networkLayer = NetworkLayer(host="192.168.31.197", port=23666)
|
|
applicationLayer = ApplicationLayer()
|
|
receiver = Receiver(networkLayer, applicationLayer)
|
|
while True:
|
|
message = networkLayer.udt_rcv()
|
|
if message:
|
|
seq_num, data = receiver.extract(message)
|
|
receiver.deliver_data(data, seq_num)
|
|
if receiver.expected_seq_num > max_seq_num:
|
|
break
|
|
print("序列传输完成。")
|
|
networkLayer.close()
|
|
|