为什么UDP和一个可靠的软件排序系统比TCP更快?

12

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

例如,RakNet 是一个流行的游戏网络引擎。它仅使用UDP进行连接,并拥有一个完整的系统,可以确保数据包在需要时是可靠和有序的。

我的基本问题是,这是怎么回事?难道TCP不就是有序、可靠的UDP吗?是什么使它如此缓慢,以至于人们必须重新发明轮子?

7个回答

15

一般/专业化

  1. TCP是一种通用可靠的系统。
  2. UDP +其他协议是一种特殊目的的可靠系统。

专业化的东西通常比通用性的东西更适合于它们所专门从事的领域。

流/消息

  1. TCP基于流。
  2. UDP基于消息。

将离散的游戏信息映射发送到基于消息的范例通常更好。将其通过流发送是可能的,但效率极低。如果您想可靠地发送大量数据(文件传输),TCP非常有效。这就是为什么Bit-torrent在控制消息中使用UDP,而在数据发送中使用TCP的原因。


14

我们在大约一年前将“英雄联盟”从可靠传输切换到不可靠传输,因为它有许多优势,这些优势后来被证明是正确的:

1)旧信息变得无关紧要。如果我发送一个健康数据包但它没有到达...我不想等待同样的健康数据包重新发送,因为我知道它已经过时了。

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

3)不可靠传输不会积压信息...即等待确认,这意味着你可以更快地解决丢失峰值问题。

4)当需要时,您可以更有效地控制重发。例如,将未发送的内容重新打包到另一个数据包中。(TCP确实可以重新打包,但您可以根据程序如何工作的知识更有效地进行操作)。

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

6)更小的头数据包...无需过多解释。


4

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

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

TCP - UDP Comparative Analysis


3
我认为答案是两个词:“拥塞控制”。
TCP非常努力地管理路径的带宽-充分利用它,但确保有其他应用程序的空间。这是一项非常艰巨的任务,本质上不可能100%地使用100%的带宽。
另一方面,使用UDP,可以制定自己的协议以任意速度将数据包发送到线路上-这使得协议对其他应用程序非常不友好,但可以在短期内获得更多“性能”。另一方面,在适当的条件下,这种协议很可能会导致拥塞崩溃的发生。

1
TCP是一种面向流的协议,而UDP是一种面向消息的协议。因此,TCP不仅提供可靠性和排序功能。有关更多详细信息,请参见this post。基本上,RakNet开发人员在保持它作为面向消息的协议的同时添加了可靠性和排序功能,因此结果比TCP更轻量级(TCP需要做更多工作)。

0

UDP 的可靠性较低,可以通过发送消息并等待响应来提高其可靠性,如果没有响应,则重新发送消息。


2
现有六个答案,其中一些已经得到社区的验证,大多数提供的细节远远超过了这个。虽然我们很高兴你急于为社区做出贡献,但请把时间集中在那些你有新信息可以添加的问题上。 - Jeremy Caney

0

这篇小文章虽然有些年头了,但在游戏领域仍然很有参考价值。它解释了两种协议以及这些人在开发多人互联网游戏“X-Wing vs Tie Fighter”时所遇到的麻烦。

吸取教训(互联网太糟糕了)

不过,这里有一个例外,我运行/开发了一个多人游戏,并且我已经使用了这两种协议。UDP对我的应用程序来说更好,但是很多人无法使用UDP进行游戏。路由器等设备会阻止连接。因此,我改用“可靠”的TCP。可靠?我不这么认为。你发送一个数据包,没有错误,你再发送另一个数据包,它就在数据包中间崩溃(异常)。现在哪些数据包被发送成功了呢?因此,你最终需要在tcp之上编写一个可靠的协议,以模拟UDP - 但在崩溃时不断建立新的连接。效率低下。

UDP + 停止等待ARQ = 不错

UDP + 滑动窗口协议 = 更好

TCP + 带重新连接的滑动窗口协议?= 无用的大块头软件。(个人意见)

另一个副作用是多线程应用程序。TCP适用于聊天室类型的应用,因为每个房间可以是自己的线程。一个房间可以容纳60-100人,运行良好,因为房间线程包含每个参与者的套接字。
另一方面,UDP最好由一个线程提供服务(在我看来),但当你收到数据包时,你必须解析它以确定它来自谁(通过发送的信息或RemoteEndPoint),然后以线程安全的方式将该数据传递给聊天室线程。
实际上,你必须对TCP做同样的事情,但只有在连接时才需要。
最后一点。请记住,TCP会在任何时候出错并终止连接,但您可以在约0.5秒内重新连接并发送相同的信息。这是我曾经遇到的最奇怪的事情。

你能详细说明一下在使用TCP时抛出的异常吗?我肯定会怪罪你的代码而不是TCP层,因为这听起来有点荒谬。不过感谢你指出滑动窗口协议,我之前没听说过,它是一个很有趣的算法。 - Ricket

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