面试题答案
一键面试协议关键部分
- 序列号(Sequence Number):为每个发送的数据包分配一个唯一的序列号,接收方可以通过序列号来确定数据包的顺序,以便正确重组数据。
- 确认机制(Acknowledgment):接收方在成功接收数据包后,向发送方发送一个确认消息(ACK),其中包含已成功接收数据包的序列号。发送方通过接收ACK来确认数据包已被成功接收。
- 重传机制(Retransmission):发送方在发送数据包后,启动一个定时器。如果在定时器超时之前没有收到对应的ACK,发送方将重传该数据包。
Python代码框架
import socket
import time
# 配置
SERVER_IP = '127.0.0.1'
SERVER_PORT = 12345
BUFFER_SIZE = 1024
TIMEOUT = 5 # 重传超时时间(秒)
# 创建UDP套接字
server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_socket.bind((SERVER_IP, SERVER_PORT))
def send_data(data, client_address):
sequence_number = 0
while data:
packet = f"{sequence_number}:{data[:BUFFER_SIZE]}"
data = data[BUFFER_SIZE:]
while True:
server_socket.sendto(packet.encode(), client_address)
start_time = time.time()
server_socket.settimeout(TIMEOUT)
try:
ack, _ = server_socket.recvfrom(BUFFER_SIZE)
ack_seq = int(ack.decode())
if ack_seq == sequence_number:
break
except socket.timeout:
print(f"重传序列号为 {sequence_number} 的数据包")
sequence_number += 1
def receive_data():
received_data = b''
expected_sequence_number = 0
while True:
packet, client_address = server_socket.recvfrom(BUFFER_SIZE)
seq, data = packet.decode().split(':', 1)
seq = int(seq)
if seq == expected_sequence_number:
received_data += data.encode()
expected_sequence_number += 1
server_socket.sendto(str(seq).encode(), client_address)
else:
# 发送最近正确接收的序列号的ACK
server_socket.sendto(str(expected_sequence_number - 1).encode(), client_address)
if len(data) < BUFFER_SIZE:
break
return received_data
if __name__ == "__main__":
choice = input("选择操作:1. 发送数据 2. 接收数据 ")
if choice == '1':
data_to_send = input("输入要发送的数据:").encode()
client_ip = input("输入客户端IP:")
client_port = int(input("输入客户端端口:"))
send_data(data_to_send, (client_ip, client_port))
elif choice == '2':
received = receive_data()
print(f"接收到的数据: {received.decode()}")
else:
print("无效选择")
上述代码框架包含了发送和接收数据的基本逻辑,发送方按照自定义协议发送数据并处理重传,接收方接收数据并发送ACK。实际应用中,可能需要根据具体需求进一步完善和优化,如处理数据包丢失、乱序等复杂情况。