为什么游戏开发人员在应用程序级别中避免使用TCP并使UDP可靠?

Non*_*one 5 networking udp tcp rudp

许多游戏开发者选择在应用程序级别使UDP 可靠.这不是TCP的用途吗?我创建了一个API,使用UDP和TCP数据包启用客户端 - 服务器通信.我应该在列表中添加Reliable UDP吗?为什么?如果我使用TCP有问题吗?

我只是想知道RUDP是否对TCP有任何好处,因此我可以选择是否添加RUDP支持.

No-*_*are 11

简短回答:TCP 没有针对延迟进行优化(根本没有);结果 - 它有几个属性是游戏的延迟杀手(尽管它们只在数据包丢失时发挥作用)。特别是,对于快节奏的游戏,队头阻塞和指数退避往往非常烦人。

对延迟影响最大的是队头阻塞(又名 HOL 阻塞):如果一个数据包丢失,则同一流中的所有后续数据包,即使它们到达通信的另一端,也不允许到达应用级(哎哟!),直到丢失的数据包被重新传输(这将需要大约 2*RTT,即使对于每个大陆的服务器,也大约是 100 毫秒(=在射击游戏中,您已经被杀了))。

长答案:

这是一个复杂的主题,我们需要区分几个不同的场景:

  1. 我们确实需要可靠的有序消息(或字节)流。在这种情况下,RUDP 相对于 TCP 的好处虽然存在,但非常小(我们可以减少重传时间 - 并消除指数退避,但仅此而已)。特别是,对于任何类型的可靠有序流(无论是 TCP、RUDP 还是其他任何类型),队头阻塞仍然是不可避免的。

  2. 我们确实需要可靠但可能无序的消息传递。这可以避免 HOL 阻塞,但需要相当复杂的应用程序级处理。

  3. 我们根本不需要可靠性(=“即发即忘”)。此类信息的一个主要示例是当我们需要显示子弹命中时 - 如果我们没有立即显示它,则无需在半秒后显示它,所以如果数据包没有成功 - 那么,最好忽略它而不是花费资源重新发送数据包。

  4. 我们确实需要最终同步状态(但我们不关心经历所有中间状态);这是模拟中极为常见的场景。这可以通过 UDP 实现(并且不会招致 HOL 阻塞惩罚)。但是 - 在不可靠的连接上启用压缩并非易事,而且对于大多数游戏来说,压缩是必须的。幸运的是 - 这种压缩是可行的(参见http://gafferongames.com/networked-physics/snapshot-compression/和/或http://ithare.com/udp-from-mog-perspective/#low-latency-compression供讨论)。如果实现这种方法(可以在完全不可靠的数据包之上完成) - 它将提供对 TCP 的非常显着的改进(它确实消除了 HOL 阻塞,所以我们谈论的是网络滴答顺序的延迟 - 这可以低至 1/120 秒~=8 毫秒 - 超过 RTT 的延迟,对于一个丢失的单个数据包而言,这些时间至少为 100 毫秒)。

侧面评论:

实际上,可以通过 TCP 模拟 UDP(消除 TCP 延迟) - 请参阅http://ithare.com/almost-zero-additional-latency-udp-over-tcp/。请注意,要使用它,上述所有内容仍应手动完成。对于可靠有序的流,仍然没有可以避免 HOL 阻塞的灵丹妙药;相反 - 这种技术允许使多个 TCP 连接的行为“几乎就像”它是不可靠但非阻塞的 UDP。


Mic*_*kyD 6

问题在于无序数据包.

在查看之后,我了解到问题是TCP想要占用所有收到的数据包,直到按照应用程序预期的顺序接收它们.这对于一个合理大小的多人游戏的性能来说可能是相当不利的,你只关心最新的玩家位置而不是几毫秒之前.

RUDP改变了这一切,只是提供了来自Unity状态的Erik的"最新数据包":

Erik-Juhl @ Unity Technologies

人们通过TCP选择UDP/RUDP的主要原因是TCP如何处理无序数据包.您可能只关心最近收到的数据包,并希望它一到达即可.在TCP中,如果您最近收到的数据包不是顺序中的下一个数据包,则在收到其他所有数据包之前,TCP将不会将其传递给您.

如果您需要保证顺序和交付,那么只需使用TCP.如果您需要保证顺序和交付,并在收到后立即获取最新的数据包,请使用RUDP. 告诉我更多......