为什么游戏开发者避免使用TCP,在应用层使UDP可靠?

9
许多游戏开发者选择在应用层使UDP变得“可靠”。那TCP不是就是为此而生的吗?我创建了一个API,允许客户端和服务器之间使用UDP和TCP数据包进行通信。我应该将可靠UDP添加到列表中吗?为什么?如果我使用TCP会有问题吗?
我只是想知道RUDP是否比TCP更有优势,这样我才能决定是否添加RUDP支持。

2
我只想知道RUDP相比TCP有哪些优势,这样我才能决定是否添加RUDP支持。 - None
1
哦,我完全误读了你问题的主体。我没有看到“在应用层使UDP可靠”。我以为这是一个TCP与UDP的问题,我的朋友,我很抱歉。 - user585968
你有任何证据支持许多游戏开发者在应用程序层面上使UDP可靠吗?对我来说,这似乎非常愚蠢,因为你所说的原因。 - David Schwartz
1
去 #gamedev(Freenode)询问游戏开发人员是否使用TCP或RUDP。他们总是会选择RUDP。然而,一些在 #reddit-gamedev 的游戏开发人员认为TCP并不那么慢,并且可以在游戏中用于确保某些数据包的可靠性。我不确定该听从哪种意见,所以我想得到更准确的答案。请查看http://gafferongames.com/networking-for-game-programmers/reliability-and-flow-control/。我仍然不确定应该选择哪个选项。 - None
4个回答

12
简短回答:TCP 对延迟没有进行优化(完全没有);因此,它具有一些对于游戏来说会导致延迟问题的属性(尽管它们只在数据包丢失时发挥作用)。特别是,在快节奏游戏中,头部阻塞和指数退避往往非常令人烦恼。
其中对延迟影响最大的是头部阻塞(也称为 HOL 阻塞):如果一个数据包丢失,同一数据流中的所有后续数据包,即使它们到达通信的另一侧,也不能到达应用程序层面(疼!),直到丢失的数据包被重新传输(这将需要约 2*RTT 的时间,即使对于大陆内的服务器,也约为 100 毫秒(="在射手游戏中,你已经被杀了"))。
详细回答:
这是一个复杂的主题,我们需要区分几种不同的情况:
我们确实需要可靠有序的消息(或字节)流。在这种情况下,RUDP 相对于 TCP 的优势非常小(我们可以稍微缩短重传时间并消除指数退避,但这基本上就是全部)。特别是,无论是 TCP、RUDP 还是其他任何可靠有序流,头部阻塞仍然是不可避免的。
我们确实需要可靠但可能无序的消息传递。这可能允许避免头部阻塞,但需要相当复杂的应用程序级处理。
我们根本不需要可靠性(="发送并忘记")。一个典型的例子是当我们需要显示子弹击中时,如果没有立即显示它,半秒钟后再显示就没有必要了,因此如果数据包没有到达,最好忽略它,不要花费资源重新发送数据包。
  • 我们确实需要最终同步状态(但我们不关心通过所有中间状态);这在模拟中是非常常见的情况。这可以在UDP上实现(并且不会产生HOL阻塞惩罚)。然而,启用非可靠连接上的压缩并不简单,而大多数游戏都必须使用压缩。幸运的是,这种压缩是可行的(请参见http://gafferongames.com/networked-physics/snapshot-compression/和/或http://ithare.com/udp-from-mog-perspective/#low-latency-compression进行讨论)。如果实施此方法(可以在完全不可靠的数据包之上完成),它将比TCP提供非常显著的改进(它确实消除了HOL阻塞,因此我们说的是网络滴答声的延迟 - 这可以低至1/120秒约8毫秒 - 而这些对于一个单独的丢失数据包的延迟至少为100毫秒)。

  • 附言:

    实际上,可以模拟UDP over TCP (消除TCP延迟)- 请参见http://ithare.com/almost-zero-additional-latency-udp-over-tcp/。注意,要利用它,仍然需要手动完成上述所有工作。仍然没有解决可靠排序流避免HOL阻塞的神奇方法;相反,这种技术允许使几个TCP连接表现得“几乎像”是不可靠但非阻塞的UDP。


    这些链接太棒了,你是我的英雄! - None

    7

    这个问题涉及到乱序数据包

    经过调查,我了解到问题在于TCP想要掌控所有接收到的数据包,直到它们按照应用程序期望的顺序被接收。这可能对一个相当大的多人游戏的性能产生不良影响,因为您只关心最新的玩家位置,而不是几毫秒前它们出现在哪里。

    RUDP改变了这一点,正如Unity的Erik所说,它只提供了"最新的数据包":

    Erik-Juhl @ Unity Technologies

    人们选择 UDP/RUDP 而不是 TCP 的主要原因是因为 TCP 处理失序数据包的方式。你可能只关心最近接收到的数据包并希望尽快获取它。在 TCP 中,如果最近接收到的数据包不是下一个顺序的数据包,TCP 将不会将其传递给你,直到所有其他数据包都被接收到。
    如果您需要保证顺序和交付,则使用 TCP。如果您需要保证顺序和交付并且尽快获取最新数据包,则使用 RUDP。了解更多...

    1
    @Am_I_Helpful 哈哈,你比我快了两分钟。祝你一切顺利 :) - user585968
    实际上,问题确实是“TCP希望独占所有接收到的数据包,直到按应用程序期望的顺序接收到它们”()。然而,在现实生活中,99%的情况并不是因为乱序数据包(这很少见),而是因为丢失数据包(这非常普遍)。这个丢失的数据包以及()一起导致所谓的Head-Of-Line Blocking(HOL Blocking),这会给快节奏的游戏带来很多麻烦。 - No-Bugs Hare

    2
    如果我直接说UDP比TCP更快,特别是用于这些应用程序,你可能不会相信和接受。因此,开发人员开展了一些关于UDP的可靠性(称为RUDP),使其有些类似于TCP。但它仍然没有完全实现TCP功能(总体上)。
    因此,我想参考一篇文章Reliable UDP (RUDP): The Next Big Streaming Protocol?来回答您的问题:
    TCP有一套指令,确保每个数据包都能到达其接收者。它类似于最基本的挂号信。然而,尽管在向他人发送东西时“确保消息到达”显然是至关重要的,但还有一些额外的注意事项必须注意。如果使用TCP/IP的网络链接注意到一个数据包到达的顺序不正确,则TCP会停止传输,丢弃从乱序数据包开始的任何内容,发送“返回到出错的地方”的消息,然后重新开始传输。
    如果你有充足的时间,这很好。所以对于将我的薪资信息从公司转移到我个人,我真的不在乎这需要微秒还是一小时,我只希望它做得正确。TCP非常适合这个任务。
    然而,在视频为中心的服务模型中,有太多的数据,如果一些数据包无法通过链路传输,那么有时我宁愿跳过那些数据包,继续整体流程的视频,而不是获取原始源的每个细节。只要我们的大脑没有被卡顿的音频和停止动画视频所干扰,我们的大脑就可以想象出视频中被跳过的部分。在这种情况下,有一个选项只需及时地从链路的一端发送尽可能多的数据,而不管有多少数据准确地到达,显然是可取的。对于这种类型的应用程序,UDP是最优选择。如果一个数据包似乎没有到达,则接收者等待几秒钟以查看是否到达--可能直到观看者需要查看该视频块的时刻--如果缓冲区到达应该有缺失数据包的位置,则简单地继续进行,并跳过缺失数据的点,继续进行下一个数据包并保持视频的时间基准。你可能会看到一些闪烁或一些伪像,但这个瞬间几乎瞬间就过去了,很可能你的大脑会填补空白。
    如果在TCP下发生此错误,则需要TCP重新协商从缺失点重新开始的顺序,这可能需要超过3秒钟,并且必须重新排队以再次发送所有后续数据。只有一个丢失的数据包就可以导致整个TCP数据“窗口”被重新发送。
    许多游戏开发者选择在应用层面上使UDP可靠。但TCP不是为此而设计的吗?
    如果您可以容忍数据在两端被处理的速度,那么这是可以的。但是,在游戏中,这是不可行的。你必须每秒传递视频帧(和音频等)给许多玩家(如果是多人游戏)。这需要更快的速度和更快的数据处理能力,而不是使用相对较慢的TCP。即使某些数据包在中途丢失了,应用程序也可以继续运行,因为大脑也会考虑下一个而不是考虑那些卡顿。
    我制作了一个API,可以使用UDP和TCP数据包进行客户端-服务器通信。我应该将可靠UDP添加到列表中吗?为什么?如果我使用TCP会有问题吗?
    这取决于您想要应用程序响应性有多好。我建议您将可靠UDP添加到您的列表中。我已经提到了TCP的问题。
    我只是想知道RUDP是否比TCP有任何优势,以便我可以选择是否添加RUDP支持。
    使用低开销和更高速度的可靠UDP,我会比笨重的TCP更有信心,用于开发这样的应用(游戏)。

    你说得更好 :) - user585968
    @MickyD - 谢谢, :) - Am_I_Helpful
    我们的大脑可以为我们想象视频中被跳过的部分,但是,假设静默地跳过丢失的数据包只影响一个帧或者更少,这个想法是错误的。对于大多数现代视频压缩来说,这种假设是致命的错误;在真实的互联网世界中,很少每一帧都是关键帧,通常关键帧相隔几秒钟;而在关键帧之后丢失的数据包将导致视频丢失,直到下一个关键帧,这通常是不可接受的。因此,现代视频流媒体主要基于TCP协议。 - No-Bugs Hare
    丢弃任何来自顺序不正确的数据包,发送“返回错误位置”的消息,并重新开始传输。这在1996年的RFC2018中得到了修复,并成为所有主要TCP协议栈实现的一部分至少15年。 - No-Bugs Hare
    继续进行整个视频的流程 - 这对任何严格的编解码器(更准确地说,对于任何没有每一帧都是关键帧的编解码器)都不起作用。 - No-Bugs Hare

    -1

    我对这些协议了解不多,但根据我的现有知识,TCP是一种面向连接的协议,而UDP是一种无连接的协议。由于UDP不会尝试进行错误恢复,因此UDP在大多数实时在线多人游戏中使用得比较频繁。在这些游戏中,UDP之所以被使用,是因为可靠性并不是非常关键。TCP会采取措施确保客户端接收到所有发送的数据包,而UDP则只是发送它们而不检查是否已经接收到。如果我说错了,请纠正我!

    参考资料:http://www.diffen.com/difference/TCP_vs_UDP


    哦,我不知道那个。 - Legoboy0215
    3
    你并没有错,但是为什么他们要让UDP变得可靠呢?难道他们不应该使用TCP吗?例如,是否存在速度差异?或者这只是在重复造轮子吗? - None
    我认为我们两个都犯了同样的错误,Lego。请注意,OP想知道为什么游戏开发人员基本上采用像UDP这样的不可靠协议,并在应用程序级别上使其可靠。 - user585968

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接