参考:https://gafferongames.com/post/reliability_ordering_and_congestion_avoidance_over_udp/
TCP有一套自己的机制来实现重传和顺序;但它因为缓冲区和顺序会有比较大的延迟。而游戏开发中通常是希望大量小延迟的传输的(甚至只有最近的几个包有用)。
UPD要实现一个不同的可靠性:稳定的发送率、收到后的回信、判断丢包率与ping
给发送数据的头部增加一个唯一ID,用来确定某个包。
ACK 也被确定回复某个收到的唯一id
ACK_BitField在上面的ACK的值上按位存储一系列的回复。比如ACK=100,ACK_BitField=10101111…,说明99收到了,98没有,96也没有等等。
一个包是否丢了,无法精确的判断。采用超时判断比较合理。
唯一ID因为可用地址有限所以需要循环使用(uint[0,4294967295] 每秒30个能发半年)。
拥塞控制:
没法控制网络上所有的路由器对拥塞的控制,所以检测到存在拥塞的话应该减少发包乃至退让。
RTT:客户端到服务器的往返时间
- 每次发包的时候本地记一下发送的时间戳
- 收到ACK之后与本地时间戳对比得出RTT
- 平滑一系列RTT RTT = RTT + 0.1 * (RTT_n – RTT)
- 丢失的包直接一个RTT_MAX(=1s,假如超时的判断就是1秒的话)
simple binary congestion avoidance(gafferong的拥塞控制算法):
有Good和Bad状态,假设每个包256Bytes,Good30包每秒,Bad10个包每秒。那么Good使用64Kbps的带宽,Bad 20Kbps。
状态的切换:
- 从Good到Bad只要RTT掉下去就好了
- Bad到Good需要RTT稳定在Good一段时间
- 防止一直变化,可设定一个状态持续时间。具体变化可以看原文。