Tcp可靠性与Udp负载对于认真,高性能的服务器

速度,优化和可扩展性是Udp和Tcp协议之间的典型比较。 Tcp吹嘘可靠性有一点额外开销的缺点,但速度很好,非常好。 一旦Tcp套接字被实例化,保持套接字打开需要一些开销。 但与Udp所描述的负担相比,哪种协议实际上有更多的开销? 我也听说过Tcp存在可扩展性问题……但是互联网(网页/服务器)在Tcp上运行 – 那么Tcp是什么阻碍了可扩展性呢?

好的…所以Udp不需要保持连接打开的开销。 但是,它要求您编写额外的方法以确保所有数据包都到达那里,希望按照您希望它接收的顺序。 如果未完整收到数据包,则必须告知客户端或服务器重新发送。 此外,您还必须为部分数据包保留某种消息收集,重建部分消息,并在最终处理消息之前检查完整的消息。 更不用说如果消息的第二部分永远不会成功,你必须要么重新发送整个事物,要么重新发送我们缺少的部分,或者其他什么。

基本上,我的问题是:

  1. 为什么我会选择Udp over Tcp来获得一个严肃的高性能服务器,它增加了消息检查和手动ACK的“开销”与连续流的“开销”?
  2. 如果Tcp对于魔兽世界来说足够好,为什么Tcp不被广泛接受作为游戏服务器使用协议?

注意:我不反对为服务器实现Udp选项。 我们在.Net 3.5框架上使用C#。 因此,我也对处理Udp 负担的最佳实践感兴趣。 我也在套接字级别使用异步方法,而不是使用TcpListener,TcpClient等。

好吧,我建议再读一些。 有很多地方可以查看TCP与UDP的专业版和内容,反之亦然,这里有几个:

  • 使用TCP over UDP有什么好处?
  • 什么时候应该使用UDP而不是TCP?
  • TCP和UDP
  • UDP over TCP有哪些优点?

但是,这个链接可能会让您感兴趣,因为它直接与网络游戏编程有关:

  • 游戏上的灯光 – UDP与TCP

如果我引用一些小的东西:

这个决定看起来很清楚,TCP做了我们想要的一切,而且它非常容易使用,而UDP是一个巨大的痛苦,我们必须从头开始编写所有内容。 显然我们只是使用TCP吗?

错误。

使用TCP是开发网络游戏时可能犯的最大错误! 要了解原因,您需要了解TCP在IP之上的实际操作,以使一切看起来如此简单!

我仍然建议你自己研究这个问题,并确保在一天结束时哪种协议适合你的需要。 话虽这么说,似乎大多数游戏都使用UDP作为他们的数据。 任何不断更新整个状态的东西都不需要保证数据包传输的开销。

首先,我将从Unix网络编程第22.4节“何时使用UDP而不是TCP”中解释史蒂文斯:

他基本上说了以下几点:

  1. UDP是广播/多播的唯一选择 – 因此您必须在那里使用它。
  2. UDP 用于简单的请求/回复应用程序。 但你必须添加自己的错误检测意味着至少ack,超时和重新传输。
  3. UDP 应该用于批量数据传输(文件传输),因为您必须在TCP中构建所有function以使其正常工作。
  4. UDP 应该用于实时数据,其中交付速度是最重要的,并且一些数据丢失不是诸如实时传感器数据,实时多媒体流,实时股票报价等的问题。

第一个问题的答案非常依赖于您对“高性能”的定义。 如果您主要担心的是低延迟,即尽可能快地到达UDP的单个数据包/请求将是最佳选择。 这有两个主要原因。 假设数据包/请求相互独立,而不是使用TCP会引入一个称为行头阻塞的问题 。

假设您发送两个独立的数据包/请求。 首先是A然后B.由于TCP是基于流的,如果A在网络中丢失并需要重新传输,那么即使B已经成功到达,也不能通过堆栈将其传送到应用程序,直到A到达,引入不必要的延迟。 不仅如此,但是在A到达之前,堆栈不能确认B,这可能导致B也被重传,从而导致不必要的网络拥塞。

解决此问题的一种方法是为每个请求使用单独的连接,但这也会引入延迟和生成系统资源。 UDP绕过所有这些问题。

高性能(低延迟)服务器中的另一个问题是Nagle算法 ,它可以在TCP通信中增加显着的延迟。

你的第二个问题的答案是WoW可能发送数据流,而不是独立的请求/回复对。 此外,通过禁用Nagle算法可以消除TCP的一些延迟。 如果他们确实使用了一些请求/回复通信,他们可能只是做出了一个设计决定,即可靠性比延迟更重要。

定义“严重的高性能” – 您在谈论多少并发连接以及流动了多少数据?

看看这个问题的答案当你需要可靠的UDP时你会用什么? 列出了一些已经在UDP上构建的可靠协议。 你可能会发现一个适合你情况的,或者你至少可以找到一些有用的想法。

在这里有效使用UDP的关键是具有一定程度的可靠性和某种程度的不可靠性,并且您可以获得更多的优势,每个数据报能够独立于其他数据报处理。 TCP的优势在于您可以对每个数据报采取行动,并决定是否可以在它到达时使用它。 这就是它适用于动作游戏的原因。

所以,恕我直言,如果您需要100%的可靠性和订单交付,那么请使用TCP; 不要尝试在UDP中重新实现TCP。

我认为TCP / IP中阻止可伸缩性的最大部分是它在所有传入/传出连接上维护一个缓冲区,基本上是窗口的大小。 因此,如果我有一个高延迟但高吞吐量的客户端我正在谈论,我必须将所有发送的数据包保留在缓冲区中,直到我收到确认。 因此,对于一些连接,这很好,但是对于处理100K连接,它可能开始成为问题的开销。 在接收端,如果数据包被丢弃,它将再次缓冲所有收到的新数据包,直到重新传输所需的数据包为止。

如果你要实现重传,你需要做同样的事情,因此会有相同的开销。 但是,如果您知道端到端链路速度,或者某些消息可能无序传送,或某些消息不需要重新传输,UDP确实为您提供了优势。 保持游戏场景:

包1 =移到1,1包2 =射包3 =移到2,2

大多数游戏设计师,如果数据包1丢失,但收到数据包3,则数据包1不再重要,因为它反正包含过时信息。 但是,您可以选择说数据包2很重要,因此如果它没有被激活,则发送重传。

如果您需要高吞吐量,并且直接使用1000Mbps以太网连接两台服务器,TCP / IP将需要一段时间进行扩展并产生额外开销,并且由于拥塞避免机制,可能永远无法实现真正​​的千兆位连接。 但是,您知道它是1 Gbps,因此您可以设置UDP自己以高达1 Gbps(减去开销)的速率进行传输。

更直接地回答你的问题:如果你要打扰每个数据包,除了你可以在等待重传时处理一些消息(除非你想要按顺序交付)之外,使用UDP并没有太大的好处。好)。

Udp不被认为是游戏服务器,主要是出于上述场景,以及实时战斗系统,例如第一人称射击游戏,可以丢弃消息,而新消息将会使丢弃的消息无效。 使用TCP可以逃避魔兽世界,因为它们不必像时间一样精确,并且可能有一些好的逻辑,这使得你更难以分辨出差异。 战斗系统根本不需要速度。

我还争辩说,一些理由是多年前保留的,当时每个人的互联网连接都不太可靠,而且速度较慢。 TCP对于共享网络也更为宽松,因此如果有很多事情发生,它将会减速,因此每个人都可以分享连接(拥塞避免)。

TCP / IP是一项由多年研究中比我聪明得多的人设计的协议。 在过去几年中进行调整使其能够以我们所看到的更快,更快的平均网络速度表现更好,并且不需要很好地理解使用。

但是,用UDP替换它确实需要对网络有一个重要的了解。 我已经看到写得很糟糕的UDP程序使1Gbps链路饱和并终止链路上的所有流量,因为它们实现了一种相当天真的重传算法。

以下是TCP / IP现在可以执行以下操作的列表: – 顺序到达您的程序 – 重新传输(现在具有快速重新传输,选择性确认和其他function) – 最大段大小 – 路径MTU发现 – 黑洞检测(路径MTU的扩展) – 拥塞避免

因此,如果适合您的需要,我强烈建议坚持使用TCP / IP。

也不是为了挑选,但你评论在TCP / IP上运行的互联网是错误的,事实上有几十个互联网可路由协议在这里检查它们 。 我认为你指的是网页和网络服务器都在TCP / IP之上运行。 对于网络而言,只要页面正确显示,我们人类就不会注意到延迟。 即使对于TCP / IP,它们也是一个挑战,TCP / IP对网络来说不够激进: 谷歌认为默认情况下tcp / ip应该更具侵略性

它的可靠性与性能。

FPS游戏不需要 – 所有数据包到达目的地,按顺序到达,特别大,或确保大吞吐量。 它们只要求数据包尽可能地到达服务器。 这是最终的优先级,TCP的开销只是一个不必要的负担。

WoW,在其“不太实时”的通信中,并且通常需要传输大量数据(在拥挤的区域中),可能必须处理超过MTU的数据包(需要分段)并且需要可靠性(更少的更大数据包=数据包丢失更多)。 因此,它对TCP的选择是合乎逻辑的。 对于大多数回合制战略游戏等也是如此。 在30分钟ping游戏的玩家用ping 50ms击败玩家的UDP是国王。