从零实现一个迷你可靠传输协议:用Python模拟RDT 2.2的停等机制

从零实现一个迷你可靠传输协议:用Python模拟RDT 2.2的停等机制 从零实现一个迷你可靠传输协议用Python模拟RDT 2.2的停等机制在分布式系统与网络编程中可靠数据传输Reliable Data Transfer是构建稳定通信的基础。本文将带您用Python从零实现RDT 2.2协议的核心机制通过代码还原停等协议Stop-and-Wait如何处理比特差错、序列号校验等经典问题。不同于单纯的理论讲解我们采用双向状态机模拟的方法让发送方与接收方的交互过程变得可视化。1. 协议核心原理拆解RDT 2.2是可靠传输协议演进过程中的关键版本它在RDT 2.1的基础上通过序列号优化消除了NAK否定确认的使用。其核心设计包含三个创新点交替序列号仅需0和1两个状态标识数据包通过模2运算实现无限循环校验和机制采用类似UDP的校验算法检测比特差错冗余ACK处理接收方通过重复发送上次ACK应对异常情况以下是对比RDT 2.1与2.2的改进要点特性RDT 2.1RDT 2.2改进点差错反馈方式使用ACK/NAK双信号仅用ACK序列号接收方缓存策略需存储最近正确数据包同左发送方重传条件收到NAK或错误ACK收到错误序列号ACK协议状态复杂度发送方需处理3种响应发送方仅处理序列号匹配2. Python实现准备2.1 基础类设计首先定义协议中使用的数据结构使用Python的dataclass简化代码from dataclasses import dataclass import random from typing import Optional dataclass class Packet: seq_num: int # 0或1的序列号 checksum: str # 校验和模拟 data: str # 实际载荷数据 dataclass class ACKPacket: ack_num: int # 确认的序列号 checksum: str # 校验和模拟2.2 信道模拟器构建一个带差错注入的虚拟信道模拟真实网络环境class UnreliableChannel: def __init__(self, error_rate0.3): self.error_rate error_rate def transmit(self, packet) - Optional[Packet]: 模拟比特差错有概率返回None表示数据损坏 if random.random() self.error_rate: return None return packet3. 发送方状态机实现发送方需维护以下状态等待上层调用准备发送新数据等待ACK已发送数据等待确认class Sender: def __init__(self): self.seq_num 0 self.buffer None self.state WAIT_CALL def rdt_send(self, data: str) - Packet: 上层调用接口 if self.state ! WAIT_CALL: raise RuntimeError(Sender not ready) packet Packet( seq_numself.seq_num, checksumself._make_checksum(data), datadata ) self.buffer packet # 缓存当前数据包 self.state WAIT_ACK return packet def handle_ack(self, ack: ACKPacket) - Optional[Packet]: 处理ACK响应 if self.state ! WAIT_ACK: return None if ack is None: # ACK传输中损坏 return self.buffer # 重传 if ack.ack_num self.seq_num: self.seq_num ^ 1 # 序列号翻转 self.state WAIT_CALL return None else: return self.buffer # 序列号不匹配需重传 def _make_checksum(self, data: str) - str: 简化的校验和生成 return bin(sum(ord(c) for c in data))[-16:]关键细节seq_num ^ 1用异或运算实现0/1交替比模运算更高效4. 接收方状态机实现接收方核心逻辑是校验数据包并返回适当ACKclass Receiver: def __init__(self): self.expected_seq 0 self.last_data None def rdt_receive(self, packet: Packet) - Optional[ACKPacket]: 处理到达的数据包 if packet is None: # 数据包损坏 return self._make_ack(self.expected_seq ^ 1) if packet.checksum ! self._calc_checksum(packet.data): return self._make_ack(self.expected_seq ^ 1) if packet.seq_num self.expected_seq: self.last_data packet.data self.expected_seq ^ 1 return self._make_ack(packet.seq_num) else: return self._make_ack(packet.seq_num ^ 1) def _make_ack(self, ack_num: int) - ACKPacket: 生成ACK包 return ACKPacket(ack_numack_num, checksumbin(ack_num)[2:].zfill(16)) def _calc_checksum(self, data: str) - str: 与发送方一致的校验算法 return bin(sum(ord(c) for c in data))[-16:]5. 完整系统模拟测试组装各个组件进行端到端测试def simulate_rdt22(): channel UnreliableChannel(error_rate0.2) sender Sender() receiver Receiver() # 模拟应用层发送数据 test_data [Hello, World, RDT, 2.2] for data in test_data: # 发送阶段 packet sender.rdt_send(data) print(f[SEND] Seq:{packet.seq_num} Data:{packet.data}) # 信道传输 recv_packet channel.transmit(packet) # 接收阶段 ack receiver.rdt_receive(recv_packet) print(f[RECV] {CORRUPT if recv_packet is None else OK}) # ACK传输 recv_ack channel.transmit(ack) res sender.handle_ack(recv_ack) # 处理重传 while res is not None: print(f[RETR] Seq:{res.seq_num}) recv_packet channel.transmit(res) ack receiver.rdt_receive(recv_packet) recv_ack channel.transmit(ack) res sender.handle_ack(recv_ack)运行结果示例[SEND] Seq:0 Data:Hello [RECV] OK [SEND] Seq:1 Data:World [RECV] CORRUPT [RETR] Seq:1 [RECV] OK [SEND] Seq:0 Data:RDT ...6. 协议优化与扩展虽然实现了基础功能但在实际应用中还可以考虑动态超时机制根据网络状况调整ACK等待时间class AdaptiveTimer: def __init__(self, initial1.0): self.timeout initial def update(self, rtt_sample): self.timeout 0.8*self.timeout 0.2*rtt_sample*2滑动窗口扩展将停等协议改进为流水线传输发送方维护发送窗口如3个包接收方支持乱序缓存拥塞控制添加简单的AIMD加性增乘性减算法def adjust_window(self, ack_received): if ack_received: self.window min(self.window 1, MAX_WINDOW) else: self.window max(self.window // 2, 1)通过这个实现过程可以清晰看到可靠传输协议如何通过序列号、校验和、重传机制三大支柱保证数据正确性。虽然现代TCP协议已经发展出更复杂的机制但这些核心思想仍然贯穿其中。