资源已经绑定,需要学习的自行下载。
1. 核心设计原理
确认与重传是可靠传输的基石,其核心逻辑是通过序列号标记数据包,接收方返回ACK确认,发送方通过超时未确认触发重传。这种方式在应用层模拟了TCP的可靠性,但需在UDP基础上自行实现。
2. 具体实现步骤
(1)数据包格式设计
每个UDP数据包需携带以下元信息(以结构体为例):
序列号(seq):递增的唯一标识,用于检测丢包、乱序(例:从1开始递增)。
确认号(ack):接收方通过ack告知发送方已成功接收的序列号。
数据内容(data):实际传输的载荷。
标志位(flag):区分数据包(DATA)和确认包(ACK)。
type packet struct {
seq int // 序列号
ack int // 确认号
data string // 数据内容
flag flagtype // 标志位(DATA/ACK)
}
(2)发送方逻辑
发送数据包:将数据封装为packet结构,通过UDP发送。
维护发送队列:缓存已发送但未确认的数据包(用于超时重传)。
启动定时器:为每个数据包设置超时时间(如500ms),若超时未收到ACK则触发重传。
// 示例:发送方循环发送并等待ACK
for i := 0; i < 5; i++ {
sendPacket := packet{seq: currentSeq, data: "hello", flag: flagData}
udpConn.Write(encode(sendPacket))
startTimer(currentSeq) // 启动定时器
waitForACK() // 阻塞等待ACK
}
(3)接收方逻辑
接收数据包:解析UDP报文,提取序列号和数据内容。
发送ACK确认:构造ACK包(ack=接收的seq+数据长度),通过UDP返回给发送方。
// 示例:接收方处理DATA包并返回ACK
recvPacket := decode(buffer)
if recvPacket.flag == flagData {
ackPacket := packet{ack: recvPacket.seq + len(recvPacket.data), flag: flagACK}
udpConn.Write(encode(ackPacket))
}
(4)超时重传策略
定时器管理:为每个数据包维护独立的超时计时器(或使用全局轮询)。
重传触发条件:若超时未收到ACK,从发送队列中取出数据包重新发送。
退避算法:动态调整超时时间(如Jacobson算法,根据RTT估算优化)。