ChatGPT解决这个技术问题 Extra ChatGPT

当您需要可靠的 UDP 时,您使用什么?

如果您遇到 TCP 连接可能太慢而 UDP“连接”可能太不可靠的情况,您会使用什么?有各种标准可靠的 UDP 协议,您对它们有什么经验?

请在每个回复中讨论一种协议,如果其他人已经提到了您使用的协议,那么请考虑对他们进行投票并在需要时使用评论进行详细说明。

我对这里的各种选项感兴趣,其中 TCP 处于规模的一端,而 UDP 处于另一端。有各种可靠的 UDP 选项可用,每个选项都为 UDP 带来了一些 TCP 元素。

我知道 TCP 通常是正确的选择,但列出替代方案通常有助于帮助人们得出这个结论。像 Enet、RUDP 等基于 UDP 构建的东西各有优劣,你用过吗,你的经验是什么?

为免生疑问,没有更多信息,这是一个假设性问题,我希望能引出一份答复清单,详细说明需要做出决定的人可以使用的各种选项和替代方案。

这个问题似乎是题外话,因为它正在轮询技术
那些认为 TCP 在所有情况下都最好的人,请阅读:en.wikipedia.org/wiki/Bandwidth-delay_product
维基百科有一个不错的 table comparing various aspects of UDP, UDP Lite, TCP, Multipath TCP, SCTP, DCCP, and RUDP。 SCTP 支持该列表中的大多数功能。
@EugeneBeresovsky 我对 SCTP 进行了一些研究,大部分信息,包括来自 SO 的答案,日期为 2013 年或更早。大多数人当时写道,SCTP 的采用率非常低。我想知道今天怎么样?另外,请参阅此线程stackoverflow.com/questions/1171555/…
@MichaelIvanov 采用率确实很低。但是如果你打算在你的数据中心内使用它,你并不关心外部采用,只要交换机和路由器不会引起问题(在数据中心,它们不应该),并且你有操作系统和库支持,这可能是一个问题,如您链接到的问题的答案的one中所述。

p
philant

SCTP 怎么样。它是 IETF (RFC 4960) 的标准协议

它具有分块功能,有助于提高速度。

更新:comparison between TCP and SCTP 表明除非可以使用两个接口,否则性能是相当的。

更新:nice introductory article


很好,我对可以构建在 UDP 之上而不是构建在 IP 之上的东西更感兴趣,但它肯定适合解决方案空间。
SCTP 具有许多出色的功能(例如多宿主),并且通过部分可靠性扩展 (RFC 3758),它是一个非常灵活的选项。它包含在最新的 linux 内核版本中,但对于 Windows,您必须安装自己的 SCTP 堆栈。
SCTP 可以通过 UDP 建立隧道。 tools.ietf.org/id/draft-ietf-sigtran-sctptunnel-00.txt
谢谢迈尔斯,这是一个有用的链接!
是的...但是建立在 UDP 之上而不是与 UDP 处于同一级别的东西可能更容易在用户空间中实现,至少在 Windows 上...
A
Andrew Edgecombe

如果没有关于问题领域的一些额外信息,很难回答这个问题。例如,您使用的数据量是多少?多常?数据的性质是什么? (例如,它是唯一的、一次性数据吗?还是样本数据流?等等)您正在为什么平台开发? (例如桌面/服务器/嵌入式)要确定您所说的“太慢”是什么意思,您使用的是什么网络介质?

但是在(非常!)一般意义上,我认为您将不得不非常努力地在速度上击败 tcp,除非您可以对您尝试发送的数据做出一些艰难的假设。

例如,如果您尝试发送的数据是这样的,您可以容忍单个数据包的丢失(例如,定期采样的数据,其中采样率比信号带宽高很多倍),那么您可能可以通过确保您可以检测数据损坏(例如,通过使用良好的 crc)来牺牲一些传输的可靠性

但是,如果您不能容忍单个数据包的丢失,那么您将不得不开始引入 tcp 已经具备的可靠性技术类型。而且,在没有投入大量工作的情况下,您可能会发现您开始将这些元素构建到用户空间解决方案中,并伴随着所有固有的速度问题。


好的,我会调整问题。我对各种可靠的 UDP 协议的优缺点更感兴趣,而不是“使用 TCP”响应;)
@Andrew - 在两种情况下击败 TCP 非常容易:(1)您的应用程序的可靠性要求比“所有数据,始终按顺序,没有重复,没有过多的排队”更轻。或者(2)您正在使用多播。可靠的 UDP 在多播环境中非常常见。
此外,在通过 WAN 连接使用时,TCP 会遭受可怕的损失(长途问题)。为什么,很简单。 TCP 使用窗口,必须确认窗口中的数据包。 ACK 协议会因为线路距离而受到延迟。谷歌:WAN TCP“光速”
@Ajaxx,您对此非常正确,但是,由于上次互联网崩溃,TCP/IP 故意这样做。如果您正在执行没有任何拥塞控制的高比特率协议,那么您基本上会感到羞耻。如果你拥有网络,那就去疯狂吧。
“采样率明显高于奈奎斯特率”——根据定义,采样率始终是奈奎斯特率的两倍。
L
Len Holgate

ENET - http://enet.bespin.org/

我使用 ENET 作为可靠的 UDP 协议,并为我的一个在他们的服务器中使用它的客户编写了一个异步套接字友好版本。它工作得很好,但我不喜欢点对点 ping 增加其他空闲连接的开销;当您有很多连接时,定期对所有连接进行 ping 操作是一项很忙的工作。

ENET 让您可以选择发送多个“通道”数据,并且发送的数据是不可靠、可靠或有序的。它还包括前面提到的点对点 ping,它充当保持活动状态。


C
Chris Markle

我们有一些国防工业客户使用 UDT(基于 UDP 的数据传输)(请参阅 http://udt.sourceforge.net/)并且对此非常满意。我看到它也有一个友好的 BSD 许可证。


您能否详细说明您的客户及其用例,尤其是在国防领域?可能不会,但值得一试。实际上,我已经向我的上级提出了关于文件传输应用程序中 UDT 的想法,但它还没有真正消失。
L
Len Holgate

任何认为上面的列表还不够,并且想要开发自己的 OWN 可靠 UDP 的人绝对应该看看 Google QUIC 规范,因为它涵盖了许多复杂的极端情况和潜在的拒绝服务攻击。我还没有尝试过它的实现,你可能不想要或不需要它提供的所有东西,但在着手新的“可靠”UDP 设计之前,该文档非常值得阅读。

QUIC 的一个很好的起点是 here,在 Chromium 博客上。

当前的 QUIC 设计文档可在 here 中找到。


L
Len Holgate

RUDP - Reliable User Datagram Protocol

这提供了:

确认收到的数据包

窗口化和拥塞控制

重传丢失的数据包

过度缓冲(比实时流更快)

在保持活动方面,它似乎比 ENet 更具可配置性,但它并没有给你太多的选择(即所有数据都是可靠的,并且不仅仅是你决定应该是的位)。它看起来相当直接实施。


我在看这个,但似乎没有很多实现。有推荐吗?
不,对不起。我最终并没有最终使用它,而是总是要从头开始实施。
s
smo

正如其他人指出的那样,您的问题非常笼统,并且是否比 TCP“更快”取决于应用程序的类型。

对于从一台主机到另一台主机的可靠数据流,TCP 通常尽可能快。但是,如果您的应用程序执行大量小流量突发并等待响应,则 UDP 可能更适合最小化延迟。

有一个简单的中间立场。 Nagle's algorithm 是 TCP 的一部分,可帮助确保发送方不会在大量数据流中使接收方不堪重负,从而导致拥塞和数据包丢失。

如果你需要 TCP 的可靠、有序的传递,以及 UDP 的快速响应,并且不需要担心发送大数据流造成的拥塞,你可以禁用 Nagle 算法:

int opt = -1;
if (setsockopt(sock_fd, IPPROTO_TCP, TCP_NODELAY, (char *)&opt, sizeof(opt)))
  printf("Error disabling Nagle's algorithm.\n");

正如我所说,假设 TCP 处于规模的一端,而 UDP 处于规模的另一端,那么还有什么。
如果你想学究气,大多数讨论的协议都是建立在 UDP 之上的。
TCP在一端而UDP在另一端的假设是错误的。例如,UDP 没有流量控制,您很容易发送数据包太快,导致中间的路由器丢弃所有数据包。那你怎么办?忽略丢失的数据包或重新发送它们?重新发送它们,您最终会或多或少地重新实现 TCP。可靠通信的另一个选择是 SCTP。
快速响应不一定等于高吞吐量。
我不同意。当 nagle 用于具有大量较小数据包的基于 TCP 的协议时,它会将它们合并在一起并创建更多更大的数据包。它会导致发送稍有延迟,因此延迟可能会略微增加。但是,关闭 nagle 时吞吐量可能会降低,因为更多的数据包 = 更多的数据包头 = 更大的开销。在 LAN 上丢弃的数据包通常与输入缓冲区填充有关。如果您有很多客户端将数据发送到同一台主机,则可能会产生零差异。我不相信关闭和打开 nagle 会在实践中产生影响。
1
17 of 26

如果您遇到 TCP 连接可能太慢而 UDP“连接”可能太不可靠的情况,您会使用什么?有各种标准可靠的 UDP 协议,您对它们有什么经验?

你句子中的关键词是“潜在地”。我认为您确实需要向自己证明,如果您需要协议的可靠性,TCP 实际上对于您的需求来说太慢了。

如果您想从 UDP 中获得可靠性,那么您基本上将在 UDP 之上重新实现 TCP 的一些功能,这可能会使事情变得比最初使用 TCP 更慢。


是的,Andrew Edgecombe 说了这么多,但是,正如我所说,我对有哪些替代方案的利弊感兴趣。如果没有该替代方案列表及其优缺点,则很难决定什么是最好的。
给定一个已知的可靠性函数,有时可以手动调整 UDP 流以超越 hte OS 中的 TCP 流。不过很少见。
@17 of 26,我同意 Len Holgate,在某些情况下 TCP 会比可靠的 UDP 慢。就像高 BDP 网络一样,假设你有 1 Gbps 的互联网连接从中国到纽约,我相信 TCP 会吸收几乎所有 1 Gbps 的速度。 TCP 更适合地球上的大多数连接,但不适用于具有高带宽延迟产品的网络。
b
bortzmeyer

协议 DCCP,在 RFC 4340 中标准化,“数据报拥塞控制协议”可能是您正在寻找的。

似乎是 implemented in Linux


b
bortzmeyer

可能是 RFC 5405,“应用程序设计者的单播 UDP 使用指南”将对您有用。


p
philant

您是否考虑过压缩数据?

如上所述,我们缺乏有关您问题的确切性质的信息,但压缩数据以传输它们可能会有所帮助。


尤其是现代压缩库。有些和 memcpy 一样快。例如lz4。
E
Engineer

RUDP。许多用于游戏的套接字服务器都实现了类似的东西。


m
mrKirushko

很难对这个问题给出一个普遍的答案,但最好的方法可能不是停留在“TCP 和 UDP 之间”的线上,而是横着走:)。

更详细的解释:

如果应用程序需要为它传输的每条数据获得确认响应,那么 TCP 的速度几乎与它获得的一样快(特别是如果您的消息远小于您的连接的最佳 MTU)并且如果您需要发送周期性数据发送出去的那一刻就过期了,那么原始 UDP 是最好的选择,原因有很多,但也不是特别考虑速度。

可靠性是一个更复杂的问题,在这两种情况下都有一定程度的相关性,并且始终取决于特定的应用程序。举个简单的例子,如果你从路由器上拔下网线,那么祝你好运,用 TCP 可靠地传送任何东西。更糟糕的是,如果您在代码中不做任何事情,那么您的操作系统很可能会在指示错误之前阻止您的应用程序几分钟,并且在许多情况下,这种延迟也是不可接受的。

因此,传统网络协议的问题通常不是关于速度或可靠性,而是关于便利性。它是关于获得 TCP 的一些特性(自动拥塞控制、自动传输单元大小调整、自动重传、基本连接管理……),同时还至少获得它错过的一些重要和有用的特性(消息边界 - 最重要的一个,连接质量监控,连接中的多个流等),而不必自己实现。

从我的角度来看,SCTP 现在看起来是最好的通用选择,但它不是很流行,并且在当今互联网上可靠地传递它的唯一现实方法仍然是将它包装在 UDP 中(可能使用 sctplib)。它仍然是一个相对基本和紧凑的解决方案,对于某些应用程序,它本身可能仍然不够。

至于更高级的选项,在一些项目中我们使用了 ZeroMQ,它工作得很好。这是一个更完整的解决方案,而不仅仅是一个网络协议(在底层它支持 TCP、UDP、几个更高级别的协议和一些本地 IPC 机制来实际传递消息)。自从发布了几个版本以来,它的初始开发人员将注意力转移到了他的新 NanoMSG 和目前最新的 NNG 库上。它没有经过彻底的开发和测试,也不是很受欢迎,但有一天它可能会改变。如果您不介意 CPU 开销和一些网络带宽损失,那么某些库可能适合您。还有一些其他面向网络的消息交换库可用。


不错的答案。我同意,SCTP 是一个不错的选择,而且很灵活。我已经通过 sctplib 和一个自制的 WebRTC 数据通道工作实现使用它,它很好。
r
rdalmeida

您应该检查 MoldUDP,它已经存在了几十年,并且被 Nasdaq 的 ITCH 市场数据馈送使用。我们的消息传递系统 CoralSequencer 使用它来实现来自中央进程的可靠多播事件流。

免责声明:我是 CoralSequencer 的开发者之一


k
kushan singh

使用 UDP 实现可靠性的最佳方式是在应用程序本身中构建可靠性(例如,通过添加确认和重传机制)


关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅