为什么是 UDP + 比 TCP 更快的软件可靠订购系统?
如今,一些游戏使用通过 UDP 传输消息的网络系统,并确保消息可靠且有序。
例如,RakNet 是一种流行的游戏网络引擎。 它仅使用 UDP 进行连接,并且拥有一个完整的系统来确保数据包可靠且有序(如果您愿意的话)。
我的基本问题是,这是怎么回事? TCP 和有序、可靠的 UDP 不是一回事吗? 是什么让它如此缓慢以至于人们不得不重新发明轮子?
Some games today use a network system that transmits messages over UDP, and ensures that the messages are reliable and ordered.
For example, RakNet is a popular game network engine. It uses only UDP for its connections, and has a whole system to ensure that packets can be reliable and ordered if you so choose.
My basic question is, what's up with that? Isn't TCP the same thing as ordered, reliable UDP? What makes it so much slower that people have to basically reinvent the wheel?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
通用/专业化
就其专业化而言,专业化的事物通常比通用化的事物更好。
流/消息
发送离散游戏信息通常更好地映射到基于消息的范例。 通过流发送它是可能的,但效率非常低。 如果要可靠地发送大量数据(文件传输),TCP 相当有效。 这就是为什么 Bit-torrent 使用 UDP 来控制消息,使用 TCP 来发送数据。
General/Specialisation
Specialized things are usually better than general purpose things for the thing they are specialized.
Stream / Message
Sending discrete gaming information maps usually better to a message-based paradigm. Sending it through a stream is possible but horribly ineffective. If you want to reliably send a huge amount of data (File transfer), TCP is quite effective. That's why Bit-torrent use UDP for control messages and TCP for data sending.
大约一年前,我们在《英雄联盟》中从可靠转变为不可靠,因为有几个优点,后来被证明是正确的:
1)旧信息变得无关紧要。 如果我发送了一个健康数据包但它没有到达...我不想在知道它发生变化时等待相同的健康数据包重新发送。
2)订单有时是不必要的。 如果我向不同的系统发送不同的消息,则可能不需要按顺序获取这些消息。 我不强迫客户端等待有序消息。
3) 不可靠不会得到消息备份...即等待确认,这意味着您可以更快地解决丢失峰值。
4) 您可以在必要时更有效地控制重新发送。 例如将未发送的内容重新打包到另一个数据包中。 (TCP 确实会重新打包,但您可以通过了解程序的工作原理来更有效地完成此操作。)
5)消息流控制,例如当网络突然激增时丢弃不太相关的消息。 当出现丢失高峰时,网络系统可以选择不重新发送不太相关的消息。 使用 TCP,您仍然会有一个尝试重新发送的消息队列,这些消息的优先级可能较低。
6) 较小的标头数据包...实际上不需要对此说太多。
We switched from reliable to unreliable in "league of legends" about a year ago because of several advantages which have since proven to be true:
1) Old information becomes irrelevant. If I send a health packet and it doesn't arrive... I don't want to have to wait for that same health packet to resend when I know its changed.
2) Order is sometimes not necessary. If I'm sending different messages to different systems it may not be necessary to get those messages in order. I don't force the client to wait for in-order messages.
3) Unreliable doesn't get backed up with messages... ie waiting for acknowledgements which means you can resolve loss spikes much more quickly.
4) You can control resends when necessarily more efficiently. Such as repacking something that didn't send into another packet. (TCP does repack but you can do it more efficiently with knowledge about how your program works.)
5) Flow control of message such as throwing away messages that are less relevant when the network suddenly spikes. The network system can choose not to resend less relevant messages when you have a loss spike. With TCP you'd still have a queue of messages that are trying to resend which may be lower priority.
6) Smaller header packet... don't really need to say much about that.
UDP 和 TCP 之间的区别不仅仅是可靠性和顺序:
问题的核心是 UDP 是无连接的,而 TCP 是有连接的。 这个简单的差异导致了许多其他差异,我无法在这里合理地总结这些差异。 您可以阅读下面的分析以了解更多详细信息。
TCP - UDP对比分析
There's much more of a difference between UDP and TCP than just reliability and sequencing:
At the heart of the matter is the fact that UDP is connectionless while TCP is connected. This simple difference leads to a host of other differences that I'm not going to be able to reasonbly summarize here. You can read the analysis below for much more detail.
TCP - UDP Comparative Analysis
我认为答案就两个字:“拥塞控制”。
TCP 竭尽全力管理路径的带宽 - 使用大部分带宽,但要确保有空间供其他应用程序使用。 这是一项非常艰巨的任务,本质上不可能在 100% 的时间使用 100% 的带宽。
另一方面,使用 UDP,人们可以制定自己的协议,以尽可能快的速度将数据包发送到网络上 - 这使得该协议对其他应用程序非常不友好,但可以在短期内获得更多“性能”。 另一方面,如果条件合适,这种协议很有可能有助于 拥塞崩溃。
The answer in in my opinion the two words: "Congestion control".
TCP goes to great lengths to manage the bandwidth of the path - to use the most of it, but to ensure that there is space for other applications. This is a very hard task, and inherently it is not possible to use 100% of the bandwidth 100% of the time.
With UDP, on the other hand, one can make their own protocol to send the packets onto the wire as fast as they want - this makes the protocol very unfriendly to other applications, but can gain more "performance" short-term. On the other hand, it is with high probability that if the conditions are appropriate, this kind of protocols might contribute to congestion collapse.
TCP是面向流的协议,而UDP是面向消息的协议。 因此 TCP 所做的不仅仅是可靠性和排序。 有关更多详细信息,请参阅这篇文章。 基本上,RakNet 开发人员添加了可靠性和排序,同时仍然保持其作为面向消息的协议,因此结果比 TCP 更轻量(它必须做更多的事情)。
TCP is a stream-oriented protocol, whereas UDP is a message-oriented protocol. Hence TCP does more than just reliability and ordering. See this post for more details. Basically, the RakNet developers added the reliability and ordering while still keeping it as a message-oriented protocol, and so the result was more lightweight than TCP (which has to do more).
这篇小文章很旧了,但对于游戏来说仍然很正确。 它解释了这两种协议,以及这些人试图开发多人网络游戏所造成的破坏。 “X-Wing vs Tie Fighter”
经验教训(互联网很糟糕)
不过,需要注意的是,我运行/开发了一款多人游戏,并且我已经使用了这两种游戏。 UDP 对于我的应用程序来说要好得多,但很多人无法使用 UDP。 路由器等阻止了连接。 所以我改成了“可靠”的TCP。 嗯……可靠吗? 我不这么认为。 您发送一个数据包,没有错误,您发送另一个数据包,它在数据包中间崩溃(异常)。 现在哪些数据包成功了? 因此,您最终会在 tcp 之上编写一个可靠的协议来模拟 UDP - 但在崩溃时不断建立新连接。 就拿低效来说吧。
UDP + 停止并等待 ARW = 好的
UDP + 滑动窗口协议 = 更好的
TCP + 带重新连接的滑动窗口协议? =毫无价值的散装货物。 (恕我直言)
另一个副作用是多线程应用程序。 TCP 非常适合聊天室类型的事物,因为每个房间都可以是它自己的线程。 一个房间可以容纳 60-100 人,并且运行良好,因为 Room 线程包含每个参与者的 Sockets。
另一方面,UDP 最好由一个线程提供服务(IMO),但是当您获取数据包时,您必须解析它以找出它来自谁(通过发送的信息或 RemoteEndPoint),然后将该数据传递到聊天室线程以线程安全的方式。
实际上,您必须对 TCP 执行相同的操作,但仅限于连接时。
最后一点。 请记住,TCP 随时都会出错并终止连接,但您可以在大约 0.5 秒内重新连接并发送相同的信息。 我曾经合作过的最奇怪的事情。
This little article is old, but it's still pretty true when it comes to games. It explains the two protocols, and the havoc these folks went trying to develop a multiplayer internet game. "X-Wing vs Tie Fighter"
Lessons Learned (The Internet Sucks)
There is one caveat to this though, I run/develop a multiplayer game, and I've used both. UDP was much better for my app, but alot of people couldn't play with UDP. Routers and such blocked the connections. So I changed to the "reliable" TCP. Well... Reliable? I don't think so. You send a packet, no errors, you send another and it crashes (exception) in the middle of the packet. Now which packets made it? So you end up writing a reliable protocol ON TOP OF tcp, to simulate UDP - but continuously establish a new connection when it crashes. Take about inefficient.
UDP + Stop and wait ARW = good
UDP + Sliding Window Protocol = better
TCP + Sliding Window Protocol with reconnection? = Worthless bulkware. (IMHO)
The other side effect is multi-threaded applications. TCP works well for a chat room type thing, since each room can be it's own thread. A room can hold 60-100 people and it runs fine, as the Room thread contains the Sockets for each participant.
UDP on the other hand is best served (IMO) by one thread, but when you get the packet, you have to parse it to figure out who it came from (via info sent or RemoteEndPoint), then pass that data to the chatroom thread in a threadsafe manner.
Actually, you have to do the same with TCP, but only on connect.
Last point. Remember that TCP will just error out and kill the connection at anytime, but you can reconnect in about .5 seconds and send the same information. Most bizzare thing I've ever worked with.
UDP 的可靠性较低,通过发送消息并等待响应(如果没有响应,则重新发送消息)来提供更高的可靠性。
UDP have a lower reliability give it more reliability by making it send a message and wait for respond if no respond came it resend the message.