为什么游戏开发者在应用层面避开TCP而让UDP可靠?

Why do game developers avoid TCP and make UDP reliable in the application level?

许多游戏开发者选择 UDP 可靠 应用级别。 TCP 不正是为此而生的吗?我制作了一个 API 来启用使用 UDP 和 TCP 数据包的客户端-服务器通信。我应该将 Reliable UDP 添加到列表中吗?为什么?如果我使用 TCP 有问题吗?

我只是想知道 RUDP 是否比 TCP 有任何好处,以便我可以选择是否添加 RUDP 支持。

我对这些协议不是很了解,但据我目前的了解,TCP是面向连接的协议,UDP是无连接协议。 UDP 主要用于实时在线多人游戏,因为 UDP 速度更快,因为不尝试错误恢复。在那些游戏中,使用 UDP 是因为可靠性并不是真正重要的。 TCP 采取措施确保所有发送的数据包都被客户端接收,而 UDP 只是发送它们而不检查它们是否已被接收。如有错误请指正!

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

如果我直接说 UDP 比 TCP 更快,那么它用于此类应用程序;你不会相信和接受。开发人员继续这样做,因此在 UDP (称为 RUDP) 上开发了一些可靠性,使其在某种程度上模仿 TCP。尽管如此,它并没有完全(全部)实现 TCP 功能。

所以我想参考一篇文章回答你的问题 Reliable UDP (RUDP): The Next Big Streaming Protocol? :

TCP has a set of instructions that ensures that each packet of data gets to its recipient. It is comparable to recorded delivery in its most basic form. However, while it seems obvious at first that "making sure the message gets there" is paramount when sending something to someone else, there are a few extra considerations that must be noted. If a network link using TCP/IP notices that a packet has arrived out of sequence, then TCP stops the transmission, discards anything from the out-of-sequence packet forward, sends a "go back to where it went wrong" message, and starts the transmission again.

If you have all the time in the world, this is fine. So for transferring my salary information from my company to me, I frankly don't care if this takes a microsecond or an hour, I want it done right. TCP is fantastic for that.

In a video-centric service model, however, there is simply so much data that if a few packets don't make it over the link there are situations where I would rather skip those packets and carry on with the overall flow of the video than get every detail of the original source. Our brain can imagine the skipped bits of the video for us as long as it's not distracted by jerky audio and stop-motion video. In these circumstances, having an option to just send as much data from one end of the link to the other in a timely fashion, regardless of how much gets through accurately, is clearly desirable. It is for this type of application that UDP is optimal. If a packet seems not to have arrived, then the recipient waits a few moments to see if it does arrive -- potentially right up to the moment when the viewer needs to see that block of video -- and if the buffer gets to the point where the missing packet should be, then it simply carries on, and the application skips the point where the missing data is, carrying on to the next packet and maintaining the time base of the video. You may see a flicker or some artifacting, but the moment passes almost instantly and more than likely your brain will fill the gap.

If this error happens under TCP then it can take TCP upward of 3 seconds to renegotiate for the sequence to restart from the missing point, discarding all the subsequent data, which must be requeued to be sent again. Just one lost packet can cause an entire "window" of TCP data to be re-sent.


Many game developers choose to a make UDP reliable in the application level. Isn't that what TCP is made for?

如果你能忍受两端处理数据的速度,那没问题。

但是,在游戏中,这是不行的。您必须每秒多次传递视频帧(和音频等),这对许多玩家(如果多人游戏)来说也是如此。这一切都需要更快的速度和更快的数据处理能力;而不是使用相对较慢的 TCP。即使中途丢弃了一些数据包,应用程序继续运行也是可以的,因为大脑也会继续下一步而不是考虑那些紧张局势。

I made an API that enables Client-Server communication using UDP and TCP packets. Should I add Reliable UDP to the list? And why? Is there a problem if I use TCP?

这取决于您希望应用程序更好地响应。我建议您将 Reliable UDP 添加到列表中。

我已经提到了 TCP 的问题。

I just want to know if RUDP has any benefits over TCP, so that I can choose whether to add RUDP support or not.

在开发此类应用程序(游戏)时,我敢打赌可靠的 UDP 比笨重的 TCP 开销低且速度更快。

问题出在乱序数据包

在查看之后我了解到问题是 TCP 想要占用所有接收到的数据包,直到它们按照应用程序期望的顺序被接收。对于大小适中的多人游戏来说,这可能会对性能产生相当大的影响,因为您只关心 最新的玩家位置 而不是他们在几毫秒前的位置。

RUDP 改变了这一切,只提供“最新数据包”,正如 Unity 的 Erik 所说:

Erik-Juhl @ Unity Technologies

The main reason people would choose UDP/RUDP over TCP is because of how TCP handles out of order packets. You may only care about the most recently received packet and want that as soon as it arrives. In TCP, if your most recently received packet is not the next one in sequence, TCP will not deliver it to you until everything else has been received.

If you need to guarantee sequence and delivery then just use TCP. If you need to guarantee sequence and delivery plus get the most recent packets as soon as they arrive, then use RUDP. Tell me more...

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

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

长答案:

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

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

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

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

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

旁注:

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