如果您遇到 TCP 连接可能太慢而 UDP“连接”可能太不可靠的情况,您会使用什么?有各种标准可靠的 UDP 协议,您对它们有什么经验?
请在每个回复中讨论一种协议,如果其他人已经提到了您使用的协议,那么请考虑对他们进行投票并在需要时使用评论进行详细说明。
我对这里的各种选项感兴趣,其中 TCP 处于规模的一端,而 UDP 处于另一端。有各种可靠的 UDP 选项可用,每个选项都为 UDP 带来了一些 TCP 元素。
我知道 TCP 通常是正确的选择,但列出替代方案通常有助于帮助人们得出这个结论。像 Enet、RUDP 等基于 UDP 构建的东西各有优劣,你用过吗,你的经验是什么?
为免生疑问,没有更多信息,这是一个假设性问题,我希望能引出一份答复清单,详细说明需要做出决定的人可以使用的各种选项和替代方案。
SCTP 怎么样。它是 IETF (RFC 4960) 的标准协议
它具有分块功能,有助于提高速度。
更新:comparison between TCP and SCTP 表明除非可以使用两个接口,否则性能是相当的。
如果没有关于问题领域的一些额外信息,很难回答这个问题。例如,您使用的数据量是多少?多常?数据的性质是什么? (例如,它是唯一的、一次性数据吗?还是样本数据流?等等)您正在为什么平台开发? (例如桌面/服务器/嵌入式)要确定您所说的“太慢”是什么意思,您使用的是什么网络介质?
但是在(非常!)一般意义上,我认为您将不得不非常努力地在速度上击败 tcp,除非您可以对您尝试发送的数据做出一些艰难的假设。
例如,如果您尝试发送的数据是这样的,您可以容忍单个数据包的丢失(例如,定期采样的数据,其中采样率比信号带宽高很多倍),那么您可能可以通过确保您可以检测数据损坏(例如,通过使用良好的 crc)来牺牲一些传输的可靠性
但是,如果您不能容忍单个数据包的丢失,那么您将不得不开始引入 tcp 已经具备的可靠性技术类型。而且,在没有投入大量工作的情况下,您可能会发现您开始将这些元素构建到用户空间解决方案中,并伴随着所有固有的速度问题。
ENET - http://enet.bespin.org/
我使用 ENET 作为可靠的 UDP 协议,并为我的一个在他们的服务器中使用它的客户编写了一个异步套接字友好版本。它工作得很好,但我不喜欢点对点 ping 增加其他空闲连接的开销;当您有很多连接时,定期对所有连接进行 ping 操作是一项很忙的工作。
ENET 让您可以选择发送多个“通道”数据,并且发送的数据是不可靠、可靠或有序的。它还包括前面提到的点对点 ping,它充当保持活动状态。
我们有一些国防工业客户使用 UDT(基于 UDP 的数据传输)(请参阅 http://udt.sourceforge.net/)并且对此非常满意。我看到它也有一个友好的 BSD 许可证。
RUDP - Reliable User Datagram Protocol
这提供了:
确认收到的数据包
窗口化和拥塞控制
重传丢失的数据包
过度缓冲(比实时流更快)
在保持活动方面,它似乎比 ENet 更具可配置性,但它并没有给你太多的选择(即所有数据都是可靠的,并且不仅仅是你决定应该是的位)。它看起来相当直接实施。
正如其他人指出的那样,您的问题非常笼统,并且是否比 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 的一些功能,这可能会使事情变得比最初使用 TCP 更慢。
您是否考虑过压缩数据?
如上所述,我们缺乏有关您问题的确切性质的信息,但压缩数据以传输它们可能会有所帮助。
很难对这个问题给出一个普遍的答案,但最好的方法可能不是停留在“TCP 和 UDP 之间”的线上,而是横着走:)。
更详细的解释:
如果应用程序需要为它传输的每条数据获得确认响应,那么 TCP 的速度几乎与它获得的一样快(特别是如果您的消息远小于您的连接的最佳 MTU)并且如果您需要发送周期性数据发送出去的那一刻就过期了,那么原始 UDP 是最好的选择,原因有很多,但也不是特别考虑速度。
可靠性是一个更复杂的问题,在这两种情况下都有一定程度的相关性,并且始终取决于特定的应用程序。举个简单的例子,如果你从路由器上拔下网线,那么祝你好运,用 TCP 可靠地传送任何东西。更糟糕的是,如果您在代码中不做任何事情,那么您的操作系统很可能会在指示错误之前阻止您的应用程序几分钟,并且在许多情况下,这种延迟也是不可接受的。
因此,传统网络协议的问题通常不是关于速度或可靠性,而是关于便利性。它是关于获得 TCP 的一些特性(自动拥塞控制、自动传输单元大小调整、自动重传、基本连接管理……),同时还至少获得它错过的一些重要和有用的特性(消息边界 - 最重要的一个,连接质量监控,连接中的多个流等),而不必自己实现。
从我的角度来看,SCTP 现在看起来是最好的通用选择,但它不是很流行,并且在当今互联网上可靠地传递它的唯一现实方法仍然是将它包装在 UDP 中(可能使用 sctplib)。它仍然是一个相对基本和紧凑的解决方案,对于某些应用程序,它本身可能仍然不够。
至于更高级的选项,在一些项目中我们使用了 ZeroMQ,它工作得很好。这是一个更完整的解决方案,而不仅仅是一个网络协议(在底层它支持 TCP、UDP、几个更高级别的协议和一些本地 IPC 机制来实际传递消息)。自从发布了几个版本以来,它的初始开发人员将注意力转移到了他的新 NanoMSG 和目前最新的 NNG 库上。它没有经过彻底的开发和测试,也不是很受欢迎,但有一天它可能会改变。如果您不介意 CPU 开销和一些网络带宽损失,那么某些库可能适合您。还有一些其他面向网络的消息交换库可用。
您应该检查 MoldUDP,它已经存在了几十年,并且被 Nasdaq 的 ITCH 市场数据馈送使用。我们的消息传递系统 CoralSequencer 使用它来实现来自中央进程的可靠多播事件流。
免责声明:我是 CoralSequencer 的开发者之一
使用 UDP 实现可靠性的最佳方式是在应用程序本身中构建可靠性(例如,通过添加确认和重传机制)