【问题标题】:Why is UDP + a software reliable ordering system faster than TCP?为什么 UDP + 一个软件可靠的订购系统比 TCP 更快?
【发布时间】:2010-11-15 02:43:23
【问题描述】:

今天的一些游戏使用通过 UDP 传输消息的网络系统,并确保消息可靠且有序。

例如,RakNet 是一个流行的游戏网络引擎。它仅使用 UDP 进行连接,并且有一个完整的系统来确保数据包的可靠性和有序性(如果您愿意的话)。

我的基本问题是,这是怎么回事? TCP 与有序的、可靠的 UDP 不是一回事吗?是什么让它变得如此缓慢以至于人们不得不重新发明轮子?

【问题讨论】:

    标签: networking tcp udp


    【解决方案1】:

    一般/专业

    1. TCP 是一个通用的可靠系统
    2. UDP +任何特殊用途的可靠系统。

    专业化的东西通常比通用的东西要好。

    流/消息

    1. TCP 是基于流的
    2. UDP 是基于消息的

    发送离散的游戏信息映射通常更适合基于消息的范例。通过流发送它是可能的,但非常无效。如果你想可靠地发送大量数据(文件传输),TCP 是相当有效的。这就是为什么 Bit-torrent 使用 UDP 发送控制消息和 TCP 发送数据的原因。

    【讨论】:

      【解决方案2】:

      大约一年前,我们在“英雄联盟”中从可靠转为不可靠,因为有几个优势后来被证明是正确的:

      1) 旧信息变得无关紧要。如果我发送了一个健康包但它没有到达……我不想在知道它发生变化时等待同一个健康包重新发送。

      2) 有时不需要订购。如果我向不同的系统发送不同的消息,则可能没有必要按顺序获取这些消息。我不强迫客户端等待有序消息。

      3) 不可靠不会得到消息的备份...即等待确认,这意味着您可以更快地解决丢失峰值。

      4) 您可以在必要时更有效地控制重新发送。例如重新包装没有发送到另一个数据包中的东西。 (TCP 确实会重新打包,但您可以通过了解您的程序如何工作来更有效地进行打包。)

      5) 消息的流控制,例如在网络突然出现峰值时丢弃不太相关的消息。当您遇到丢失高峰时,网络系统可以选择不重新发送不太相关的消息。使用 TCP,您仍然会有一个尝试重新发送的消息队列,这些消息的优先级可能较低。

      6) 较小的标头数据包...不需要多说。

      【讨论】:

        【解决方案3】:

        UDP 和 TCP 之间的区别远不止可靠性和顺序:

        问题的核心在于 UDP 是无连接,而 TCP 是已连接。这个简单的差异导致了许多其他差异,我无法在此合理地总结。您可以阅读下面的分析以了解更多详细信息。

        TCP - UDP Comparative Analysis

        【讨论】:

          【解决方案4】:

          在我看来答案就两个字:“拥塞控制”。

          TCP 竭尽全力管理路径的带宽——充分利用它,但要确保有空间供其他应用程序使用。这是一项非常艰巨的任务,本质上不可能在 100% 的时间内使用 100% 的带宽。

          另一方面,使用 UDP,人们可以制定自己的协议以尽可能快地将数据包发送到线路上 - 这使得该协议对其他应用程序非常不友好,但可以在短期内获得更多“性能” .另一方面,如果条件合适,这种协议很有可能会促成congestion collapse

          【讨论】:

            【解决方案5】:

            TCP 是面向流的协议,而 UDP 是面向消息的协议。因此,TCP 所做的不仅仅是可靠性和排序。有关详细信息,请参阅this post。基本上,RakNet 开发人员增加了可靠性和排序,同时仍将其作为面向消息的协议,因此结果比 TCP 更轻量级(必须做更多)。

            【讨论】:

              【解决方案6】:

              这篇小文章很老了,但在游戏方面它仍然很真实。它解释了这两种协议,以及这些人试图开发多人网络游戏所造成的破坏。 “X翼对战平手”

              Lessons Learned (The Internet Sucks)

              对此有一个警告,我运行/开发了一款多人游戏,并且我都使用过。 UDP 对我的应用程序来说要好得多,但是很多人无法使用 UDP。路由器等阻止了连接。所以我改用“可靠”的TCP。嗯……可靠吗?我不这么认为。您发送一个数据包,没有错误,您发送另一个数据包,它在数据包中间崩溃(异常)。现在哪些数据包成功了?因此,您最终在 tcp 之上编写了一个可靠的协议,以模拟 UDP - 但在崩溃时不断建立新连接。拿一下效率低下。

              UDP + 停止并等待 ARW = 好

              UDP + 滑动窗口协议 = 更好

              重新连接的 TCP + 滑动窗口协议? = 毫无价值的散装件。 (恕我直言)

              另一个副作用是多线程应用程序。 TCP 适用于聊天室类型的东西,因为每个房间都可以是它自己的线程。一个房间可以容纳 60-100 人并且运行良好,因为房间线程包含每个参与者的套接字。

              另一方面,UDP 最好由一个线程提供服务(IMO),但是当您获取数据包时,您必须解析它以找出它来自谁(通过发送的信息或 RemoteEndPoint),然后将该数据传递给以线程安全的方式聊天室线程。

              实际上,您必须对 TCP 执行相同的操作,但仅在连接时。

              最后一点。请记住,TCP 会随时出错并终止连接,但您可以在大约 0.5 秒内重新连接并发送相同的信息。我用过的最奇怪的东西。

              【讨论】:

              • 你能详细说明一下你使用TCP时抛出的异常吗?我肯定会责怪你的代码而不是 TCP 层,因为这听起来有点荒谬。感谢您指出滑动窗口协议,但我没有听说过它,这是一个有趣的算法。
              【解决方案7】:

              UDP 具有较低的可靠性,通过使其发送消息并等待响应来提供更高的可靠性,如果没有响应,它会重新发送消息。

              【讨论】:

              • 现有的答案有六个,其中一些已经过社区验证,其中大部分提供的细节远不止于此。虽然我们很高兴您渴望为社区做出贡献,但请将您的时间集中在您有新信息要添加的问题上。
              猜你喜欢
              • 2018-12-25
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-05-09
              • 1970-01-01
              • 2016-09-19
              • 2017-04-05
              • 1970-01-01
              相关资源
              最近更新 更多