严肃的高性能服务器的 Tcp 可靠性与 Udp 负担
速度、优化和可扩展性是 Udp 和 Tcp 协议之间的典型比较。 Tcp 吹捧可靠性,但缺点是需要一点额外的开销,但速度却非常好。一旦 Tcp 套接字被实例化,保持套接字打开需要一些开销。但与经常描述的 Udp 负担相比,哪种协议实际上具有更多开销?我还听说 Tcp 存在可扩展性问题...但是 Internet(网页/服务器)在 Tcp 上运行 - 那么 Tcp 是什么抑制了可扩展性呢?
好的...所以 Udp 不需要保持连接打开的开销。但是,它要求您编写额外的方法来确保所有数据包都到达那里,希望按照您希望的接收顺序。如果数据包未完整接收,则必须告诉客户端或服务器重新发送。您还必须为部分数据包保留某种消息集合,重建部分消息,并在最终处理消息之前检查完整的消息。更不用说如果消息的第二部分永远无法发送,您必须要么重新发送整个消息,要么重新发送我们丢失的部分,或者其他什么。
基本上,我的问题是:
- 为什么我会选择 Udp 而不是 Tcp 作为一个严肃的、高性能的服务器,并增加了消息的“开销” 检查和手动 ACK 与连续流的“开销”?
- 如果 Tcp 对于《魔兽世界》之类的游戏来说足够好,为什么 Tcp 没有被更广泛地接受为用于游戏服务器的协议?
注意:我并不反对为服务器实现 Udp 选项。我们在 .Net 3.5 框架上使用 C#。因此,我也对处理 Udp 负担的最佳实践感兴趣。我还在 socket 级别使用异步方法,而不是使用 TcpListener、TcpClient 等。
Speed, optimization, and scalability are the typical comparisons between the Udp and Tcp protocols. Tcp touts reliability with the disadvantage of a little extra overhead, but speed is good to excellent. Once a Tcp socket is instanced, keeping the socket open requires some overhead. But compared to the oft described burdens of Udp, which protocol actually has more overhead?. I've also heard that there are scalability issues with Tcp...yet the Internet (Web pages/servers) runs on Tcp - so what is it about Tcp that inhibits scalability?
Okay...so Udp doesn't require that overhead of keeping a connection open. But, it requires that you write extra methods to ensure all of the packet gets there, hopefully in the order that you want it received. If a packet isn't received in full, then you have to tell the client or server to resend. And you also have to keep some sort of message collection for partial packets, rebuild the partial messages, and check for a complete message before the message can finally be processed. Not to mention if the second part of a message never makes it, you have to either say resend the entire thing, or resend the part we are missing, or whatever.
Basically, my questions are:
- Why would I choose Udp over Tcp for a serious, high-performance server with the added "overhead" of message
checking and manual ACK versus the "overhead" of a continuous stream? - If Tcp is good enough for the likes of World of Warcraft, why isn't Tcp more widely accepted as the protocol to use for a game server?
Note: I am not opposed to implementing Udp options for a server. We are using C# on .Net 3.5 framework. So I would also be interested in the best practices for dealing with Udp burdens. I am also using the asynchronous methods at the socket level rather than using TcpListener, TcpClient, etc. etc.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
嗯,我建议你多读一些书。有很多地方可以了解 TCP 与 UDP 的优缺点,反之亦然,以下是一些:
但是,此链接可能是您最感兴趣的,因为它直接与网络相关游戏编程:
如果我想引用一些小事:
不过,我仍然建议您自己对此事进行研究,并确保最终哪个协议适合您的需求。话虽如此,大多数游戏似乎确实使用 UDP 来传输数据。任何持续更新整个状态的东西都不需要保证数据包传送的开销。
Well, I would recommend reading up some more. There are plenty places to look at the pro's and con's of TCP vs. UDP and vice versa, here are a few:
However, this link may interest you the most, as it is directly about networked game programming:
If I were to quote something small:
I still recommend doing your own research on the matter though, and make sure which of the protocols suits your needs at the end of the day. This being said, it does seem to be the case that majority of games use UDP for their data. Anything that updates the entire state continuously does not need the overhead of guaranteed packet delivery.
首先,我将解释一下 Stevens 的 Unix 网络编程第 22.4 节“何时使用 UDP 而不是 TCP”
:基本上是这样的:
答案你的第一个问题很大程度上取决于你对“高性能”的定义。如果您主要关心的是低延迟,即单个数据包/请求尽可能快地到达,那么 UDP 将是最佳选择。造成这种情况的主要原因有两个。假设数据包/请求彼此相当独立,而不是使用 TCP,则会引入一个称为 head- 的问题离线阻塞。
假设您发送两个独立的数据包/请求。首先是 A,然后是 B。由于 TCP 是基于流的,如果 A 在网络中丢失并且需要重新传输,那么即使 B 已经成功到达,在 A 到达之前堆栈也无法将其传送给应用程序,从而引入不必要的延迟。不仅如此,在 A 到达之前,B 无法被堆栈确认,这可能会导致 B 也被重新传输,从而导致不必要的网络拥塞。
解决此问题的一种方法是对每个请求使用单独的连接,但这也会引入延迟并占用系统资源。 UDP 绕过了所有这些问题。
高性能(低延迟)服务器中的另一个问题是 Nagle 算法,它会显着增加延迟在 TCP 通信中。
第二个问题的答案是,魔兽世界可能发送数据流,而不是独立的请求/回复对。此外,可以通过禁用 Nagle 算法 来消除 TCP 的部分延迟。如果他们确实使用某些请求/回复通信,他们可能只是做出了一个设计决策,即可靠性对他们来说比延迟更重要。
First, I'll just paraphrase Stevens from Unix Network Programming Section 22.4 "When to Use UDP instead of TCP":
He basically says the following:
The answer to your first question is very dependent on your definition of "high-performance". If you're primary concern is low latency, i.e. the individual data packets / requests arriving as quickly as possible than UDP would be the way to go. There are two primary reasons for this. Assuming packets / requests are fairly independent of each other than using TCP would introduce a problem known as head-of-line blocking.
Let's say you send two independent packets / requests. First A then B. Since TCP is stream based, if A get's lost in the network and needs to be retransmitted then even if B has already successfully arrived it can't be delivered to the application by the stack until A arrives, introducing unnecessary latency. Not only that, but until A arrives, B can't be acknowledged by the stack which might cause B to also be retransmitted causing needless network congestion.
One way around this problem is to use separate connections for each request, however this also introduces latency and hogs system resources. UDP bypasses all these problems.
Another issue in high performance ( low latency ) servers is the Nagle Algorithm which can add significant latency in TCP communications.
The answer to your second question is that WoW probably sends streams of data, not independent request / reply pairs. Also, some of the latency of TCP can be removed by disabling the Nagle algorithm. If they do use some request / reply communications they may have simply made a design decision that reliability is more important to them than latency.
定义“真正的高性能”——您谈论的是多少个并发连接以及有多少数据正在流动?
看看这个问题的答案 你在什么情况下使用什么你需要可靠的 UDP? 其中列出了一些已经构建在 UDP 上的可靠协议。您可能会找到一种适合您情况的方法,或者您至少可以找到一些有用的想法。
在这里有效使用 UDP 的关键是具有一定程度的可靠性和一定程度的不可靠性,并且每个数据报越能够独立于其他数据报进行处理,您就会获得更多优势。相对于 TCP 的优点是,您可以对每个数据报进行操作,并在数据报到达时决定是否可以使用它。这就是为什么它适用于动作游戏。
所以,恕我直言,如果您需要 100% 的可靠性并且需要订单交付,那么请选择 TCP;不要尝试在 UDP 中重新实现 TCP。
Define "serious high performance" - how many concurrent connections are you talking about and how much data is flowing?
Take a look at the answers to this question What do you use when you need reliable UDP? which list some of the reliable protocols that have already been built on UDP. You might find one that works for your situation, or you may at least find some useful ideas.
The key to using UDP effectively here is to have some level of reliability and some level of unreliability and you get more of an advantage the more each datagram is able to be handled independently of others. The advantage over TCP is that you get to act on each datagram and decide if you can use it as it arrives. This is why it works for action games.
So, IMHO, if you need 100% reliability AND in order delivery then go with TCP; don't try and reimplement TCP in UDP.
我认为 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 现在可以做的事情,而如果使用 UDP,则无法做到这些事情:
- 为了到达您的计划
- 重传(现在具有快速重传、选择性确认和其他功能)
- 最大段大小
- 路径MTU发现
- 黑洞检测(路径MTU的扩展)
- 拥塞避免
因此,如果 TCP/IP 适合您的需要,我强烈建议您坚持使用它。
也不是为了挑剔,但是您对 TCP/IP 上运行的互联网的评论是错误的,实际上有数十种互联网可路由协议 在这里查看。我认为您指的是网页和 Web 服务器都在 TCP/IP 之上运行。这对于网络来说也是很棒的,只要页面正确显示,我们人类就不会注意到延迟。即使对于 TCP/IP,也存在一些挑战,即 TCP/IP 对于 Web 来说还不够激进:Google 认为默认情况下 tcp/ip 应该更加激进
I think the biggest part of TCP/IP that inhibits scalability is that it maintains a buffer on all incoming / outgoing connections up to basically the size of the window. So if I have a high latency but high throughput client i'm talking to, I have to keep all sent packets in buffer until I receive an ack. So for a few connections this is fine, but for handling 100K connections, it can start to be problematic overhead. On the receiving end, if a packet is dropped, again it will buffer all new packets received until the one required is retransmitted.
If you're going to implement retransmission, you need to do the same thing, and hence will have the same overhead. However, UDP does give you an advantage, if you know the end-to-end link speeds, or if certain message can be delivered out of order, or certain messages don't need retransmission. Keeping the gaming scenario:
packet 1 = move to 1,1
packet 2 = shoot
packet 3 = move to 2,2
Most game designers, if packet 1 is lost, but packet 3 is received, packet 1 is no longer important because it contains out of date information anyways. However, you could opt to say packet 2 is important, so if it's not acked, send a retransmission.
If you need high throughput, and connect two servers directly with 1000Mbps ethernet, TCP/IP will take awhile to scale and have additional overhead, and will likely never achieve a true gigabit connection due to the congestion avoidance mechanisms. However, you know it's 1 Gbps, so you can set up you're UDP to transmit at up to a 1 Gbps (minus overhead) yourself.
To answer you're questions more directly:
If you are going to ack every packet anyways, there isn't a massive benefit to having UDP, other than you can process some messages while waiting for retransmission (unless you want in-order delivery as well).
Udp isn't considered for game servers as much, mainly out of the scenario above, and real time combat systems such as First person shooters, where a message can be dropped, and the new message to come will invalidate the dropped message anyways. World of warcraft can get away with using TCP, since they don't have to be as precise with timing, and likely have some good logic that makes it more difficult for you to tell the difference anyways. The combat system simply doesn't require the speed.
I'd also contend that some of the justification is holdover from years ago, when everyone had less-reliable, and slower Internet connections. TCP is also more lenient for sharing the network, so if there's a lot going on, it will slow down so everyone gets a share of the connection (congestion avoidance).
TCP/IP is a protocol designed by people far smarter than I over years of research. Tuning in the last several years has allowed it to perform better with the faster and faster average network speeds we are seeing, and doesn't require a great understanding to use.
However, replacing this with UDP, does require a significant understanding of networking. I've seen badly written UDP programs saturate 1Gbps links and kill all traffic on the link, because they implemented a rather naive retransmission algorithm.
Here's a list of things TCP/IP can now do that you'd loose by going UDP:
- In order arrival to you're program
- retransmission (Now with Fast retransmit, selective acknowledgement, and other features)
- Maximum segment size
- Path MTU Discovery
- Black Hole Detection (extension of Path MTU)
- Congestion avoidance
Because of this, I'd highly recommend sticking with TCP/IP if it suits you're needs.
Also not to nit pick, but you're comment about the Internet running on TCP/IP is wrong, there are in fact dozens of Internet routeable protocols check them out here. I think you were referring to web pages and web servers are all running on top of TCP/IP. Which again for the web is great where us humans won't notice a delay as long as the page shows up correctly. Even for TCP/IP, their is some challenge that TCP/IP isn't aggressive enough for the web: Google thinks tcp/ip should be more aggressive by default
这是可靠性与性能。
FPS 游戏不需要所有数据包都能到达目的地、按顺序到达、特别大或确保大吞吐量。他们只要求数据包尽快到达服务器。这是最终的优先级,而 TCP 的开销根本就是不必要的负担。
WoW 在其“不太实时”的通信中并且通常需要传输大量数据(在拥挤的区域),可能必须处理超过 MTU 的数据包(需要分段)并且需要可靠性(较大的数据包越少 = 数据包丢失造成的伤害更大)。所以它选择TCP是合乎逻辑的。大多数回合制策略游戏等也是如此。在 ping 为 30ms 的玩家击败 ping 50ms 的玩家的游戏中,UDP 为王。
It's Reliability vs Performance.
FPS games don't require -all- the packets to reach the destination, to reach it in order, to be exceptionally big, or to assure big throughput. They only require the packets to reach the server AS SOON AS POSSIBLE. This is the ultimate priority and overhead of TCP is simply an unnecessary burden.
WoW, in its "not quite realtime" communication and often tons of data to transmit (in crowded areas), may have to deal with packets exceeding MTU (requiring fragmentation) and requires reliability (fewer bigger packets = packet lost hurts more). So its choice of TCP is logical. Same would go for most turn-based strategy games and the like. In games where the player with ping of 30ms beats the player with ping 50ms UDP is the king.