当您需要可靠的 UDP 时您会使用什么?
如果您遇到 TCP 连接可能太慢而 UDP“连接”可能太不可靠的情况,您会使用什么? 有各种标准的可靠 UDP 协议,您对它们有什么经验?
请针对每个回复讨论一种协议,如果其他人已经提到了您使用的协议,请考虑对它们进行投票,并在需要时使用评论进行详细说明。
我对这里的各种选项感兴趣,其中 TCP 位于天平的一端,UDP 位于另一端。 有各种可靠的 UDP 选项可用,每个选项都将 TCP 的一些元素引入 UDP。
我知道 TCP 通常是正确的选择,但拥有一份替代方案列表通常有助于帮助人们得出该结论。 像Enet、RUDP等基于UDP构建的东西有各种优缺点,你用过它们吗?你的经验是什么?
为避免疑义,没有更多信息,这是一个假设的问题,我希望能引发一系列答复,详细说明需要做出决定的人可以使用的各种选项和替代方案。
If you have a situation where a TCP connection is potentially too slow and a UDP 'connection' is potentially too unreliable what do you use? There are various standard reliable UDP protocols out there, what experiences do you have with them?
Please discuss one protocol per reply and if someone else has already mentioned the one you use then consider voting them up and using a comment to elaborate if required.
I'm interested in the various options here, of which TCP is at one end of the scale and UDP is at the other. Various reliable UDP options are available and each brings some elements of TCP to UDP.
I know that often TCP is the correct choice but having a list of the alternatives is often useful in helping one come to that conclusion. Things like Enet, RUDP, etc that are built on UDP have various pros and cons, have you used them, what are your experiences?
For the avoidance of doubt there is no more information, this is a hypothetical question and one that I hoped would elicit a list of responses that detailed the various options and alternatives available to someone who needs to make a decision.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(15)
我们有一些国防工业客户使用 UDT(基于 UDP 的数据传输)(请参阅 http://udt.sourceforge.net/ )并且对此非常满意。 我发现它也有一个友好的 BSD 许可证。
We have some defense industry customers that use UDT (UDP-based Data Transfer) (see http://udt.sourceforge.net/) and are very happy with it. I see that is has a friendly BSD license as well.
任何认为上面的列表还不够并且想要开发自己的可靠 UDP 的人一定应该看看 Google QUIC 规范,因为它涵盖了许多复杂的极端情况和潜在的拒绝服务攻击。 我还没有尝试过它的实现,您可能不想要或不需要它提供的所有内容,但在开始新的“可靠”UDP 设计之前,该文档非常值得阅读。
QUIC 的一个很好的起点是这里,位于铬博客。
您可以在此处找到当前的 QUIC 设计文档。
Anyone who decides that the list above isn't enough and that they want to develop their OWN reliable UDP should definitely take a look at the Google QUIC spec as this covers lots of complicated corner cases and potential denial of service attacks. I haven't played with an implementation of this yet, and you may not want or need everything that it provides, but the document is well worth reading before embarking on a new "reliable" UDP design.
A good jumping off point for QUIC is here, over at the Chromium Blog.
The current QUIC design document can be found here.
ENET - http://enet.bespin.org/
我使用 ENET 作为可靠的 UDP 协议,并为我的一个在服务器中使用它的客户编写了一个异步套接字友好版本。 它工作得很好,但我不喜欢点对点 ping 给空闲连接带来的开销; 当您有很多连接时,定期对所有连接执行 ping 操作是一项非常繁忙的工作。
ENET 为您提供了发送多个数据“通道”的选项,以及发送的数据可以是不可靠的、可靠的或有序的。 它还包括前面提到的点对点 ping,它充当保持活动状态。
ENET - http://enet.bespin.org/
I've worked with ENET as a reliable UDP protocol and written an asynchronous sockets friendly version for a client of mine who is using it in their servers. It works quite nicely but I don't like the overhead that the peer to peer ping adds to otherwise idle connections; when you have lots of connections pinging all of them regularly is a lot of busy work.
ENET gives you the option to send multiple 'channels' of data and for the data sent to be unreliable, reliable or sequenced. It also includes the aforementioned peer to peer ping which acts as a keep alive.
如果没有关于问题领域的一些附加信息,很难回答这个问题。
例如,您使用的数据量是多少? 多常? 数据的本质是什么? (例如,它是唯一的一次性数据吗?还是样本数据流?等等)
你是为什么平台开发的? (例如桌面/服务器/嵌入式)
要确定“太慢”的含义,您使用的网络介质是什么?
但总的来说,我认为你必须非常努力地在速度上击败 tcp,除非你可以对你试图发送的数据做出一些艰难的假设。
例如,如果您尝试发送的数据可以容忍单个数据包的丢失(例如,定期采样的数据,其中采样率比信号带宽高很多倍),那么您可能可以通过确保您可以检测数据损坏(例如,通过使用良好的 crc)来牺牲传输的一些可靠性。
但是,如果您不能容忍单个数据包的丢失,那么您将不得不开始引入技术类型对于tcp已经具备的可靠性。 而且,如果不投入合理的工作量,您可能会发现您开始将这些元素构建到用户空间解决方案中,并伴随着所有固有的速度问题。
It's difficult to answer this question without some additional information on the domain of the problem.
For example, what volume of data are you using? How often? What is the nature of the data? (eg. is it unique, one off data? Or is it a stream of sample data? etc.)
What platform are you developing for? (eg. desktop/server/embedded)
To determine what you mean by "too slow", what network medium are you using?
But in (very!) general terms I think you're going to have to try really hard to beat tcp for speed, unless you can make some hard assumptions about the data that you're trying to send.
For example, if the data that you're trying to send is such that you can tolerate the loss of a single packet (eg. regularly sampled data where the sampling rate is many times higher than the bandwidth of the signal) then you can probably sacrifice some reliability of transmission by ensuring that you can detect data corruption (eg. through the use of a good crc)
But if you cannot tolerate the loss of a single packet, then you're going to have to start introducing the types of techniques for reliability that tcp already has. And, without putting in a reasonable amount of work, you may find that you're starting to build those elements into a user-space solution with all of the inherent speed issues to go with it.
SCTP 怎么样。 它是 IETF (RFC 4960) 的标准协议,
具有有助于提高速度的分块功能。
更新:TCP 和 SCTP 之间的比较表明,除非可以使用两个接口,否则性能相当。
更新:不错的介绍性文章。
What about SCTP. It's a standard protocol by the IETF (RFC 4960)
It has chunking capability which could help for speed.
Update: a comparison between TCP and SCTP shows that the performances are comparable unless two interfaces can be used.
Update: a nice introductory article.
RUDP - 可靠用户数据报协议
它提供:
在保持活动方面,它似乎比 ENet 稍微更可配置,但它没有为您提供尽可能多的选项(即所有数据都是可靠的并且排序的,而不仅仅是您决定应该排序的位)。 它看起来相当容易实施。
RUDP - Reliable User Datagram Protocol
This provides:
It seems slightly more configurable with regards to keep alives then ENet but it doesn't give you as many options (i.e. all data is reliable and sequenced not just the bits that you decide should be). It looks fairly straight forward to implement.
使用UDP实现可靠性的最佳方法是在应用程序本身中构建可靠性(例如,通过添加确认和重传机制)
The best way to achieve reliability using UDP is to build the reliability in the application program itself( for example, by adding acknowledgment and retransmission mechanisms)
很难对这个问题给出一个通用的答案,但最好的方法可能不是停留在“TCP 和 UDP 之间”,而是走一边:)。
更详细一点的解释:
如果应用程序需要为其传输的每条数据获取确认响应,那么 TCP 的速度几乎是最快的(特别是如果您的消息远小于连接的最佳 MTU),并且如果您如果需要定期发送数据,而这些数据在发送出去后就会过期,那么原始 UDP 是最佳选择,原因有很多,但也不是特别考虑到速度。
可靠性是一个更复杂的问题,在这两种情况下它都是相对的,并且总是取决于特定的应用。 举一个简单的例子,如果您从路由器上拔掉互联网电缆,那么祝您好运,通过 TCP 可靠地传送任何内容。 更糟糕的是,如果您不在代码中对此进行处理,那么您的操作系统很可能会在指示错误之前阻止您的应用程序几分钟,并且在许多情况下,这种延迟也是不可接受的。
因此,传统网络协议的问题通常不在于速度或可靠性,而在于便利性。 它是关于获得 TCP 的一些功能(自动拥塞控制、自动传输单元大小调整、自动重传、基本连接管理……),同时还至少获得它错过的一些重要且有用的功能(消息边界 - 最重要的)重要的是,连接质量监控,连接内的多个流等),而不必自己实现。
从我的角度来看,SCTP 现在看起来是最好的通用选择,但它并不是很流行,并且当今可靠地在互联网上传递它的唯一现实方法仍然是将其包装在 UDP 中(可能使用 sctplib)。 它仍然是一个相对基本和紧凑的解决方案,对于某些应用程序来说,它本身可能仍然不够。
至于更高级的选项,在一些项目中我们使用了 ZeroMQ 并且它工作得很好。 这是一个更完整的解决方案,而不仅仅是一个网络协议(在幕后它支持 TCP、UDP、一些更高级别的协议和一些本地 IPC 机制来实际传递消息)。 自几个版本发布以来,其最初的开发人员已将注意力转移到新的 NanoMSG 和当前最新的 NNG 库上。 它没有经过彻底的开发和测试,也不是很受欢迎,但有一天它可能会改变。 如果您不介意 CPU 开销和一些网络带宽损失,那么某些库可能适合您。 还有一些其他面向网络的消息交换库可用。
It is hard to give a universal answer to the question but the best way is probably not to stay on the line "between TCP and UDP" but rather to go sideways :).
A bit more detailed explanation:
If an application needs to get a confirmation response for every piece of data it transmits then TCP is pretty much as fast as it gets (especially if your messages are much smaller than optimal MTU for your connection) and if you need to send periodic data that gets expired the moment you send it out then raw UDP is the best choice for many reasons but not particularly for speed as well.
Reliability is a more complex question, it is somewhat relative in both cases and it always depends on a specific application. For a simple example if you unplug the internet cable from your router then good luck keeping reliably delivering anything with TCP. And what even worse is that if you don't do something about it in your code then your OS will most likely just block your application for a couple of minutes before indicating an error and in many cases this delay is just not acceptable as well.
So the question with conventional network protocols is generally not really about speed or reliability but rather about convenience. It is about getting some features of TCP (automatic congestion control, automatic transmission unit size adjustment, automatic retransmission, basic connection management, ...) while also getting at least some of the important and useful features it misses (message boundaries - the most important one, connection quality monitoring, multiple streams within a connection, etc) and not having to implement it yourself.
From my point of view SCTP now looks like the best universal choice but it is not very popular and the only realistic way to reliably pass it across the Internet of today is still to wrap it inside UDP (probably using sctplib). It is also still a relatively basic and compact solution and for some applications it may still be not sufficient by itself.
As for the more advanced options, in some of the projects we used ZeroMQ and it worked just fine. This is a much more of a complete solution, not just a network protocol (under the hood it supports TCP, UDP, a couple of higher level protocols and some local IPC mechanisms to actually deliver messages). Since a couple of releases its initial developer has switched his attention to his new NanoMSG and currently the newest NNG libraries. It is not as thoroughly developed and tested and it is not very popular but someday it may change. If you don't mind the CPU overhead and some network bandwidth loss then some of the libraries might work for you. There are some other network-oriented message exchange libraries available as well.
您应该检查 MoldUDP,它已经存在了几十年,并且被纳斯达克的 ITCH 使用市场数据馈送。 我们的消息系统 CoralSequencer 使用它来实现可靠的多播事件流一个中心过程。
免责声明:我是 CoralSequencer 的开发者之一
You should check MoldUDP, which has been around for decades and it is used by Nasdaq's ITCH market data feed. Our messaging system CoralSequencer uses it to implement a reliable multicast event-stream from a central process.
Disclaimer: I'm one of the developers of CoralSequencer
您是否考虑过压缩数据?
如上所述,我们缺乏有关您的问题的确切性质的信息,但压缩数据以传输它们可能会有所帮助。
Did you consider compressing your data ?
As stated above, we lack information about the exact nature of your problem, but compressing the data to transport them could help.
可能是 RFC 5405,“应用程序设计者的单播 UDP 使用指南”对于你。
May be RFC 5405, "Unicast UDP Usage Guidelines for Application Designers" will be useful for you.
协议 DCCP,在 RFC 4340 中标准化,“数据报拥塞控制协议”可能就是您想要的正在找。
似乎在 Linux 中实现。
Protocol DCCP, standardized in RFC 4340, "Datagram Congestion Control Protocol" may be what you are looking for.
It seems implemented in Linux.
RUDP。 许多游戏的套接字服务器都实现了类似的东西。
RUDP. Many socket servers for games implement something similar.
你这句话中的关键词是“潜在”。 我认为如果您需要协议的可靠性,您确实需要向自己证明 TCP 事实上对于您的需求来说太慢了。
如果您想从 UDP 中获得可靠性,那么您基本上将在 UDP 之上重新实现 TCP 的一些功能,这可能会使事情比一开始就使用 TCP 慢。
The key word in your sentence is 'potentially'. I think you really need to prove to yourself that TCP is, in fact, too slow for your needs if you need reliability in your protocol.
If you want to get reliability out of UDP then you're basically going to be re-implementing some of TCP's features on top of UDP which will probably make things slower than just using TCP in the first place.
正如其他人指出的那样,您的问题非常笼统,并且某些东西是否比 TCP“更快”在很大程度上取决于应用程序的类型。
TCP 通常能够尽可能快地将数据从一台主机可靠地传输到另一台主机。 但是,如果您的应用程序执行大量小流量突发并等待响应,则 UDP 可能更适合最大限度地减少延迟。
有一个简单的中间立场。 Nagle 算法 是 TCP 的一部分,有助于确保发送方不会压倒接收方大量数据流,导致拥塞和丢包。
如果你既需要 TCP 的可靠、有序的传递,又需要 UDP 的快速响应,并且不需要担心发送大数据流造成的拥塞,你可以禁用 Nagle 算法:
As others have pointed out, your question is very general, and whether or not something is 'faster' than TCP depends a lot on the type of application.
TCP is generally as fast as it gets for reliable streaming of data from one host to another. However, if your application does a lot of small bursts of traffic and waiting for responses, UDP may be more appropriate to minimize latency.
There is an easy middle ground. Nagle's algorithm is the part of TCP that helps ensure that the sender doesn't overwhelm the receiver of a large stream of data, resulting in congestion and packet loss.
If you need the reliable, in-order delivery of TCP, and also the fast response of UDP, and don't need to worry about congestion from sending large streams of data, you can disable Nagle's algorithm: