用于一般协议消息交换,可以容忍一些丢包。UDP 比 TCP 效率高多少?
14 回答
人们说 TCP 给你的主要东西是可靠性。但事实并非如此。TCP 为您提供的最重要的东西是拥塞控制:您可以在 DSL 链路上运行 100 个 TCP 连接,所有这些连接都以最大速度运行,并且所有 100 个连接都将是高效的,因为它们都“感知”了可用带宽。尝试使用 100 个不同的 UDP 应用程序,所有应用程序都尽可能快地推送数据包,看看效果如何。
在更大的范围内,这种 TCP 行为是防止 Internet 陷入“拥塞崩溃”的原因。
倾向于将应用程序推向 UDP 的事情:
组交付语义:可以比 TCP 的点对点确认更有效地向一群人进行可靠的交付。
乱序交付:在很多应用中,只要你得到所有的数据,你并不关心它是按什么顺序到达的;您可以通过接受无序块来减少应用程序级延迟。
不友好:在 LAN 聚会上,您可能不在乎您的 Web 浏览器是否运行良好,只要您尽可能快地向网络发送更新即可。
但即使您关心性能,您也可能不想使用 UDP:
您现在正处于可靠性的困境中,并且您可能为实现可靠性所做的许多事情最终可能比 TCP 已经做的要慢。
现在您对网络不友好,这可能会导致共享环境出现问题。
最重要的是,防火墙会阻止您。
通过将多个 TCP 连接“中继”在一起,您可以潜在地克服一些 TCP 性能和延迟问题;iSCSI 这样做是为了绕过局域网上的拥塞控制,但您也可以这样做来创建一个低延迟的“紧急”消息通道(TCP 的“紧急”行为完全被破坏了)。
在某些应用程序中,TCP 比 UDP 更快(更好的吞吐量)。
相对于 MTU 大小进行大量小写入时就是这种情况。例如,我阅读了一个实验,其中通过以太网(1500 字节 MTU)发送 300 字节数据包流,并且TCP 比 UDP 快 50%。
原因是 TCP 会尝试缓冲数据并填充整个网段,从而更有效地利用可用带宽。
另一方面,UDP 立即将数据包放在网络上,从而使网络因大量小数据包而拥塞。
除非您有非常具体的原因,否则您可能不应该使用 UDP。特别是因为您可以通过禁用Nagle 算法来为 TCP 提供与 UDP 相同的延迟(例如,如果您正在传输实时传感器数据并且您不担心大量小数据包使网络拥塞)。
UDP 比 TCP 快,原因很简单,因为它不存在允许连续数据包流的确认数据包 (ACK),而不是使用 TCP 窗口大小和往返时间计算的确认一组数据包的 TCP (RTT)。
有关更多信息,我推荐简单但非常易于理解的Skullbox 解释(TCP vs. UDP)
具有容错性
你的意思是“有损失容忍度”吗?
基本上,UDP 不是“容错”的。您可以向某人发送 100 个数据包,他们可能只收到其中的 95 个数据包,而且有些数据包的顺序可能错误。
对于像视频流和多人游戏这样的事情,最好是错过一个数据包而不是延迟它后面的所有其他数据包,这是显而易见的选择
但是,对于大多数其他事情,丢失或“重新排列”的数据包至关重要。您必须编写一些额外的代码才能在 UDP 之上运行,以便在遗漏时重试,并强制执行正确的顺序。这会在某些地方增加一点开销。
值得庆幸的是,一些非常非常聪明的人已经做到了这一点,他们称之为 TCP。
可以这样想:如果一个数据包丢失,您是希望尽快获取下一个数据包并继续(使用 UDP),还是您真的需要丢失的数据(使用 TCP)。除非您处于非常极端的情况,否则开销无关紧要。
当谈到“更快”时 - 至少有两个非常不同的方面:吞吐量和延迟。
如果谈到吞吐量- TCP 的流量控制(如其他答案中所述)非常重要,并且在 UDP 上做任何可比的事情,虽然当然可能,但将是一个巨大的头痛(tm)。结果 - 当您需要吞吐量时使用 UDP很少有资格作为一个好主意(除非您想获得相对于 TCP 的不公平优势)。
但是,如果谈到延迟- 整个事情就完全不同了。虽然在没有数据包丢失的情况下,TCP 和 UDP 的行为非常相似(任何差异,如果有的话,都是微不足道的)——在数据包丢失之后,整个模式发生了巨大的变化。
在任何数据包丢失后,TCP 将等待重新传输至少 200 毫秒(根据 RFC6298 的第 2.4 段 1 秒,但实际的现代实现倾向于将其减少到 200 毫秒)。此外,使用 TCP,即使是那些确实到达目标主机的数据包 - 在收到丢失的数据包之前不会被传递到您的应用程序(即整个通信延迟约 200 毫秒) - 顺便说一句,这种效果,称为 Head-of -线路阻塞是所有可靠有序流所固有的,无论是 TCP 还是可靠+有序 UDP。更糟糕的是——如果重传的数据包也丢失了,那么我们将讨论约 600 毫秒的延迟(由于所谓的指数退避,第一次重传是 200 毫秒,第二次重传是 200*2=400 毫秒)。如果我们的频道有 1% 的丢包率(按照今天的标准,这还不错),我们有一个每秒更新 20 次的游戏——这样的 600 毫秒延迟平均每 8 分钟发生一次。因为 600 毫秒足以让你在快节奏的游戏中丧命 - 嗯,这对游戏玩法来说非常糟糕。这些影响正是游戏开发者通常更喜欢 UDP 而不是 TCP 的原因。
然而,当使用 UDP 来减少延迟时 - 重要的是要意识到仅仅“使用 UDP”不足以显着改善延迟,这完全取决于您如何使用 UDP。特别是,虽然 RUDP 库通常避免“指数退避”并使用更短的重传时间——如果它们被用作“可靠的有序”流,它们仍然必须遭受行头阻塞(所以在双丢包,而不是 600 毫秒,我们将得到大约 1.5 * 2 * RTT - 或者对于一个相当不错的 80 毫秒 RTT,这是一个大约 250 毫秒的延迟,这是一个改进,但仍然可以做得更好)。另一方面,如果使用http://gafferongames.com/networked-physics/snapshot-compression/和/或http://ithare 中讨论的技术。,有可能完全消除 Head-of-Line 阻塞(因此对于每秒 20 次更新的游戏的双包丢失,无论 RTT 如何,延迟都将为 100 毫秒)。
作为旁注 - 如果您碰巧只能访问 TCP 而没有 UDP(例如在浏览器中,或者如果您的客户端位于阻止 UDP 的 6-9% 的丑陋防火墙之一) -似乎有一种方法可以实现 UDP-over-TCP 而不会产生太多延迟,请参见此处:http: //ithare.com/almost-zero-additional-latency-udp-over-tcp/(请务必阅读评论(!))。
哪种协议性能更好(在吞吐量方面) - UDP 或 TCP - 实际上取决于网络特性和网络流量。例如,Robert S. Barnes 指出了 TCP 性能更好的场景(小型写入)。现在,考虑一个网络拥塞并且同时具有 TCP 和 UDP 流量的场景。网络中使用 TCP 的发送者将感知“拥塞”并降低其发送速率。但是,UDP 没有任何拥塞避免或拥塞控制机制,使用 UDP 的发送者将继续以相同的速率泵入数据。渐渐地,TCP 发送者将他们的发送速率降低到最低限度,如果 UDP 发送者有足够的数据通过网络发送,他们将占用大部分可用带宽。所以,在这种情况下,UDP 发送者将拥有更大的吞吐量,因为他们获得了更大的网络带宽。事实上,这是一个活跃的研究课题——如何在存在 UDP 流量的情况下提高 TCP 吞吐量。据我所知,使用 TCP 应用程序可以提高吞吐量的一种方法是打开多个 TCP 连接。这样,即使每个 TCP 连接的吞吐量可能受到限制,所有 TCP 连接的吞吐量总和也可能大于使用 UDP 的应用程序的吞吐量。
每个 TCP 连接都需要在传输数据之前进行初始握手。此外,TCP 标头包含大量用于不同信号和消息传递检测的开销。对于消息交换,如果可以接受很小的失败几率,UDP 可能就足够了。如果必须验证收据,TCP 是您的最佳选择。
我会把事情说清楚。 TCP/UDP是两辆在路上行驶的汽车。假设交通标志和障碍物是错误TCP关心交通标志,尊重周围的一切。慢速驾驶,因为汽车可能会出事。虽然UDP只是开车,全速不尊重路标。没什么,一个疯狂的司机。UDP没有错误恢复,如果有障碍物,它只会与它发生碰撞然后继续。虽然TCP确保所有数据包都被完美地发送和接收,没有错误,所以,汽车只是通过障碍物而不会发生碰撞。我希望这是一个很好的例子让你理解为什么UDP在游戏中是首选。游戏需要速度。 下载时首选TCP,否则下载的文件可能已损坏。
根据我的经验,UDP 稍微快一些,但速度并不快。不应根据性能做出选择,而应根据消息内容和压缩技术做出选择。
如果它是带有消息交换的协议,我建议您使用 TCP 对性能造成的轻微影响是非常值得的。您将获得两个端点之间的连接,这将为您提供所需的一切。不要尝试在 UDP 之上制造自己的可靠双向协议,除非您对自己的工作非常非常有信心。
请记住,TCP 通常在线上保留多条消息。如果你想在 UDP 中实现这一点,如果你想可靠地做到这一点,你将做很多工作。您的解决方案要么变得不那么可靠,要么变得不那么快,或者工作量大得惊人。有 UDP 的有效应用程序,但如果您问这个问题,您的问题可能不是。
已经完成了一些工作,以使程序员能够同时获得两全其美的好处。
SCTP
它是一个独立的传输层协议,但它可以用作一个库,在 UDP 上提供额外的层。通信的基本单元是消息(映射到一个或多个 UDP 数据包)。内置拥塞控制。协议有旋钮和旋钮可以打开
- 为了传递消息
- 使用用户定义的参数自动重传丢失的消息
如果您的特定应用程序需要任何这些。
一个问题是连接建立是一个复杂的过程(因此过程很慢)
其他类似的东西
另一件类似的专有实验物
这也试图改进 TCP 的三次握手并改变拥塞控制以更好地处理快速线路。
如果您需要在两个尚未通话的 IP 之间通过网络快速发送消息,那么 UDP 的到达速度至少要快 3 倍,通常要快 5 倍。
不考虑网络情况,谈 TCP 或 UDP 是没有意义的。如果两点之间的网络质量非常高,UDP 绝对比 TCP 快,但在其他一些情况下,例如 GPRS 网络,TCP 可能比 UDP 更快、更可靠。
网络设置对于任何测量都至关重要。如果您通过本地计算机上的套接字或与世界的另一端进行通信,这将产生巨大的差异。
我想在讨论中添加三件事:
- 你可以在这里找到一篇关于游戏开发环境中 TCP 与 UDP 的非常好的文章。
- 此外,iperf(jperf使用 GUI 增强 iperf)是一个非常好的工具,可以通过测量自己回答您的问题。
- 我在 Python 中实现了一个基准测试(参见这个 SO question)。对于 UDP,平均 10^6 次迭代发送 8 个字节的差异约为 1-2 微秒。