Linux下Python UDP传输优化求助:已实现Go-Back-N仍速度迟缓
UDP文件传输工具优化问题
我需要为Linux创建一个Python UDP工具,目前能正常传输文件,但速度非常慢,且无法针对丢包场景进行优化。我已经实现了Go-Back-N算法和动态超时机制,但传输速度仍未达标。以下是我的代码:
客户端代码
import socket import struct import time import sys # Constants SERVER_ADDRESS = ('localhost', 12345) CHUNK_SIZE = 1024 HEADER_FORMAT = "I" INITIAL_TIMEOUT = 0.5 WINDOW_SIZE = 4 MIN_TIMEOUT = 0.1 MAX_TIMEOUT = 2.0 def calculate_new_timeout(estimated_rtt, sample_rtt, alpha=0.125, beta=0.25): if estimated_rtt is None: estimated_rtt = sample_rtt else: estimated_rtt = (1 - alpha) * estimated_rtt + alpha * sample_rtt adjusted_timeout = estimated_rtt + beta * estimated_rtt return max(MIN_TIMEOUT, min(adjusted_timeout, MAX_TIMEOUT)) def send_chunk(s, chunk, seq_num): try: packet = struct.pack(HEADER_FORMAT, seq_num) + chunk s.sendto(packet, SERVER_ADDRESS) except socket.error as err: print(f"Error sending packet {seq_num}: {err}") def send_file(filename): s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.settimeout(INITIAL_TIMEOUT) estimated_rtt = None packets_in_flight = {} start_time = time.time() try: with open(filename, 'rb') as f: eof = False seq_num = 0 while not eof: while len(packets_in_flight) < WINDOW_SIZE and not eof: chunk = f.read(CHUNK_SIZE) if chunk == b'': eof = True chunk = b'EOF' send_chunk(s, chunk, seq_num) packets_in_flight[seq_num] = (chunk, time.time()) seq_num += 1 while packets_in_flight: try: ack, _ = s.recvfrom(CHUNK_SIZE) ack_num, = struct.unpack(HEADER_FORMAT, ack) if ack_num in packets_in_flight: sample_rtt = time.time() - packets_in_flight[ack_num][1] del packets_in_flight[ack_num] estimated_rtt = calculate_new_timeout(estimated_rtt, sample_rtt) s.settimeout(estimated_rtt) except socket.timeout: for seq_num, (chunk, _) in packets_in_flight.items(): send_chunk(s, chunk, seq_num) finally: duration = time.time() - start_time print(f'File sent successfully in {duration:.2f} seconds.') s.close() if __name__ == "__main__": if len(sys.argv) != 2: print("Usage: python client.py <filename>") sys.exit(1) send_file(sys.argv[1])
服务端代码
import socket import struct import sys # Constants LISTEN_ADDRESS = ('localhost', 12345) BUFFER_SIZE = 2048 HEADER_FORMAT = "I" def receive_file(save_as): s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.bind(LISTEN_ADDRESS) print("Server started. Waiting for data...") expected_seq_num = 0 try: with open(save_as, 'wb') as f: while True: packet, client_address = s.recvfrom(BUFFER_SIZE) seq_num, = struct.unpack(HEADER_FORMAT, packet[:struct.calcsize(HEADER_FORMAT)]) data = packet[struct.calcsize(HEADER_FORMAT):] if seq_num == expected_seq_num: if data == b'EOF': print("EOF received. Ending transmission.") ack_packet = struct.pack(HEADER_FORMAT, expected_seq_num) s.sendto(ack_packet, client_address) break f.write(data) expected_seq_num += 1 ack_packet = struct.pack(HEADER_FORMAT, expected_seq_num - 1) s.sendto(ack_packet, client_address) finally: s.close() print(f"File received successfully and saved as {save_as}.") if __name__ == "__main__": if len(sys.argv) != 2: print("Usage: python server.py <save_as_filename>") sys.exit(1) receive_file(sys.argv[1])
可行的优化方法
1. 调整窗口与数据包尺寸
- 增大
WINDOW_SIZE:当前值为4过小,可根据带宽延迟乘积(BDP)计算最优值,公式为BDP = 带宽(Mbps) * 延迟(ms) / 8,得到字节数后除以单包大小得到窗口数量,初始可尝试32或64。 - 优化
CHUNK_SIZE:Linux下UDP单包建议接近MTU(1472字节,MTU1500减去IP头20+UDP头8),减少数据包数量,降低协议开销。
2. 改进重传逻辑
- 超时后仅重传最早未确认的包,而非所有在途包,减少不必要的流量消耗;同时为每个包单独设置定时器,精准触发重传。
- 实现快速重传:当收到3个重复ACK时,立即重传对应缺失的包,无需等待超时,降低延迟。
3. 异步IO与多线程优化
- 使用
selectors模块实现异步IO,同时处理发送、接收和超时事件,避免阻塞导致窗口无法及时填充。 - 分离文件读取和网络发送线程:文件读取线程提前将数据块读入缓冲区,网络线程直接从缓冲区取数据发送,避免磁盘IO阻塞传输。
4. 优化ACK机制
- 服务端支持选择性ACK(SACK):收到乱序包时,在ACK中附带已接收的乱序包序号,让客户端仅重传缺失的包。
- 延迟ACK:服务端合并多个ACK为一个发送(比如每收到N个包或延迟10ms发送一次),减少反向流量开销。
5. 系统层面优化
- 增大Linux UDP缓冲区:通过
sysctl命令调整参数,避免缓冲区不足导致丢包:sysctl -w net.core.rmem_max=16777216 sysctl -w net.core.wmem_max=16777216 - 在代码中设置socket缓冲区大小:调用
s.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 16777216)和对应接收缓冲区参数。
6. 细节优化
- 将
packets_in_flight改为有序数据结构(如列表),快速定位最早未确认的包,提升重传效率。 - 提前计算结构体头长度,避免重复调用
struct.calcsize。 - 增加数据包校验:在头部加入CRC校验码,服务端验证数据完整性,避免因数据损坏导致无效重传。
内容的提问来源于stack exchange,提问作者Dr.Labradoor
相关产品推荐
相关产品推荐

