




UDP不保证可靠性,需应用层实现丢包检测与补偿;Golang无内置UDP丢包检测API,可通过序列号、超时重传、ACK及统计窗口构建轻量级可靠层;序列号+时间戳标记数据包,接收端依序号缓存并检测空缺,注意序列号回绕处理。
UDP本身不保证可靠性,检测丢包和实现补偿必须由应用层自行设计。Golang中没有内置的“UDP丢包检测API”,但可以通过序列号、超时重传、ACK机制和统计窗口等手段,在UDP之上构建轻量级可靠性层。
发送端为每个UDP数据包添加自增序列号(uint32足够)和可选纳秒级时间戳。接收端按序号缓存已收包,发现空缺(如收到#5后直接收到#7)即可判定#6丢失。注意处理序列号回绕(mod 2³²),用有符号差值判断顺序:
发送端维护未确认包的map[seq]time.Time,并启动goroutine定期扫描:若某seq超过RTT阈值(如200ms)未收到ACK,就重发。接收端收到包后立即发回轻量ACK(仅含原seq),避免ACK风暴可启用批量ACK或延迟ACK(≤50ms):
单纯重传不控速会导致网络拥塞加剧丢包。引入固定大小滑动窗口(如32个slot),只有窗口内seq允许发送;收到ACK后窗口右移。窗口大小可根据RTT波动动态调整(如初始32,连续丢包则减半):
立即学习“go语言免费学习笔记(深入)”;
在接收端周期性(如每秒)计算最近N个包的丢包率(lost/total),当持续高于阈值(如15%)时,主动降速:增大RTO、缩小窗口、降低发送频率。也可将该指标通过控制面反馈给发送端,实现双向调节:

基本上就这些。Golang的goroutine和channel让这类状态管理很自然,但要注意UDP无连接特性——所有可靠性逻辑都得自己扛。不复杂但容易忽略的是边界处理:序列号回绕、超时定时器泄漏、大窗口下的内存占用。上线前务必用tc netem模拟丢包(tc qdisc add dev lo root netem loss 10%)压测验证。