MST

星途 面试题库

面试题:Python实现UDP可靠通信的自定义协议设计

假设现有一个基于Python的UDP通信场景,需要在不可靠的UDP基础上实现可靠的数据传输,设计一个简单的自定义协议来确保可靠性,描述协议的关键部分(如序列号、确认机制、重传机制等),并给出Python代码框架来实现这个协议。
39.7万 热度难度
编程语言Python

知识考点

AI 面试

面试题答案

一键面试

协议关键部分

  1. 序列号(Sequence Number):为每个发送的数据包分配一个唯一的序列号,接收方可以通过序列号来确定数据包的顺序,以便正确重组数据。
  2. 确认机制(Acknowledgment):接收方在成功接收数据包后,向发送方发送一个确认消息(ACK),其中包含已成功接收数据包的序列号。发送方通过接收ACK来确认数据包已被成功接收。
  3. 重传机制(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。实际应用中,可能需要根据具体需求进一步完善和优化,如处理数据包丢失、乱序等复杂情况。