我正在研究UDP服务器/客户端配置。客户端向服务器发送单个数据包,其大小不同,但通常为500字节。服务器基本上立即响应一个输出数据包,通常比传入的请求数据包小。完整的事务总是由单个数据包交换组成。
如果客户端在T时间内没有看到响应,则重试R次,在每次重试之前将T增加X,最后放弃并返回错误。目前,R是不会改变的。
是否有特殊的逻辑来选择最优的初始T(等待时间),R(重试)和X(等待增加)?重试的持续时间应该有多长(即,使用的最小R值是多少)才能达到某种近似的"可靠"协议?
这与问题5227520类似。在谷歌上搜索"tcp retries"one_answers"tcp retransmission",会得到许多多年来被尝试过的建议。不幸的是,没有一个解决方案是最优的。
我会选择T从2或3秒开始。我增加的X将是T的一半(翻倍T似乎很流行,但很快就会出现很长的超时)。如果有必要,我会将R调整为至少5或更多,因此我的总超时至少是一分钟或两分钟。
如果后续交易通常更快,我会小心不要让R和T太高;你可能想要降低R和T,因为你的统计允许,所以你可以重试,并得到一个快速的响应,而不是离开R和T在他们的最大值(特别是如果你的客户是人类,你想要响应)。
请记住:你永远不会像一个重试次数比你多的算法那样可靠,如果那些重试成功的话。另一方面,如果你的服务器总是可用的,并且总是"立即响应",那么如果客户端没有看到响应,这是服务器无法控制的失败,唯一可以做的就是客户端重试(尽管重试可以不仅仅是重新发送,例如关闭/重新打开连接,在不同的IP上尝试备份服务器,等等)。
最小超时应该是路径延迟,或者RTT(往返时间)的一半。
参见RFC 908 -可靠数据协议。
最大的问题是决定一个超时后会发生什么,你重置到相同的超时还是你加倍?这是一个复杂的决定,取决于交流的大小、频率,以及你希望与他人游戏的公平程度。
如果你发现数据包经常丢失,并且延迟是一个问题,那么你需要考虑保持相同的超时或缓慢上升到指数超时,例如1x, 1x, 1x, 1x, 2x, 4x, 8x, 16x, 32x。
如果带宽不是太大的问题,但延迟确实是,那么遵循基于udp的数据传输协议(UDT),并通过低超时和冗余交付强制数据通过。这对于广域网环境非常有用,特别是洲际距离,这也是为什么UDT经常出现在广域网加速器中。
更有可能的是,延迟不是那么重要,并且更倾向于其他协议的公平性,然后使用标准的后退模式,1x, 2x, 4x, 8x, 16x, 32x。
理想情况下,应该改进协议处理的实现,以自动导出最佳超时和重试周期。当没有数据丢失时,您不需要冗余交付,当有数据丢失时,您需要增加交付。对于超时,您可能希望考虑在最佳条件下减少超时,然后在发生拥塞时放慢速度,以防止同义广播风暴。