UDP可以重传丢失的数据吗?
我知道该协议不支持这一点,但是对于需要一定程度的可靠性的客户端来说,在其应用程序中构建一种在发现数据包损坏时请求重传的方法是否很常见?
I know the protocol doesn't support this but is it common for clients that require some level of reliability to build into their application a method for requesting retransmission of a packet if found to be corrupt?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
如果客户端需要可靠性(或者有时只是一些可靠性),但不需要 TCP 提供的任何其他功能,例如严格的按顺序交付,那么客户端通常会在 UDP 之上实现可靠性。如果他们同时想要低延迟(或多播,只要它有效)。
一般来说,只有在有紧急原因(需要非常低的延迟和高速度,例如抽搐游戏)时,您才需要使用可靠的 UDP。在每种“正常”情况下,简单地使用 TCP 都会为您提供同样好的服务或更好。
另请注意,在 UDP 之上实现您自己的堆栈很容易,但其性能比 TCP 更差。
请参阅 enet 以获取在 UDP 之上实现可靠性(以及一些其他功能)的库示例 (Raknet或 HawkNL 是其他示例)。
It is common for clients to implement reliability on top of UDP if they need reliability (or sometimes just some reliability) but not any of the other things that TCP offers, for example strict in-order delivery, and if they want, at the same time, low latency (or multicast, where it works).
In general, you will only want to use reliable UDP if there are urgent reasons (very low latency and high speed needed, e.g. for a twitch game). In every "normal" case, simply using TCP will serve you equally well or better.
Also note that it is easy to implement your own stack on top of UDP that performs worse than TCP.
See enet for an example of a library that implements reliability (and some other features) on top of UDP (Raknet or HawkNL would be other examples).
您可能想查看此问题的答案:做什么当你需要可靠的UDP时你使用什么?
You might want to look at the answers to this question: What do you use when you need reliable UDP?
当然。您可以在 UDP 之上构建可靠的协议(如 TCP)。
示例
假设您正在构建一个文件服务器:
* 使用 1024 字节的块读取文件
* 构造一个 UDP 数据包,其有效负载:4 个字节表示文件中的“位置”,4 个字节表示数据包内容的“长度”。
接收方现在接收 UDP 数据包。如果他收到以下数据包:
* 0-1024:数据
* 1024-2048:数据
* 3072-4096:DATA
它意识到数据包丢失,并要求发送应用程序重新发送 2048 和 3072 之间的部分。
这是一个非常基本的示例,用于解释您的应用程序代码需要处理数据包构造和有效负载解释。不要使用它,它不考虑边缘情况(最后一个数据包、损坏数据包的校验和……)。
Of course. You can build a reliable protocol (like TCP) on top of UDP.
Example
Imagine you are building a fileserver:
* read the file using blocks of 1024 bytes
* construct an UDP packet with payload: 4 bytes for the "position" in the file, 4 bytes for the "length" of the contents of the packet.
The receiver now receives UDP packets. If he gets following packets:
* 0-1024: DATA
* 1024-2048: DATA
* 3072-4096: DATA
it realises a packet got missing, and asks the sending application to resend the part between 2048 and 3072.
This is a very basic example to explain your application code needs to deal with the packet construction and payload interpretation. Don't use it, it does not take edge cases (last packet, checksums for corrupted packets, ...) into account.
简短回答:不。
详细回答:UDP 不关心数据包丢失。如果 UDP 数据包到达且校验和错误,则该数据包将被简单地丢弃。数据包的发送者和接收者都不会收到此通知。它只是被丢弃,这就是所发生的一切。另外,UDP 数据包没有编号,因此,如果您发送了 4 个数据包,但只有 3 个到达接收方,接收方无法知道原来有 4 个数据包,其中丢失了 1 个。最后但并非最不重要的一点是,数据包不会被确认,因此发送方永远不会知道它发出的数据包是否已到达接收方。
与此相反,TCP 将数据分成段,每个段都有编号,因此接收方可以知道某个段是否丢失。此外,所有段都必须向发送者确认。如果发送方在一段时间后没有收到某个报文段的确认,它将认为该报文段丢失并重新发送。
当然,您可以在通过 UDP 发送的每个数据片段之上添加自己的帧头,这样您的应用程序代码就可以对发送的片段进行编号,并且您可以在代码中实现确认重发策略,但问题是:这会吗?真的比 TCP 已经免费提供的更好吗?即使它同样好,也可以节省时间并使用 TCP。很多人已经认为他们可以比 TCP 做得更好,但通常他们最终意识到,实际上他们做不到。 TCP 有其弱点,但总的来说它非常擅长它的功能。
Short answer: No.
Long answer: UDP doesn't care for packet loss. If an UDP packet arrives and has a bad checksum, it is simply dropped. Neither the sender of the packet is informed about this, nor the recipient is informed. It is only dropped, that's all that happens. Also UDP packets are not numbered, so if you send four packets and only three arrive at the recipient, the recipient cannot know that there used to be four and one is missing. Last but not least, packets are not acknowledged, so the sender will never know if a packet it was sending out ever made it to the recipient or not.
Contrary to this, TCP breaks data into segments, each segment is numbered, so the recipient can know if a segment is missing. Also all segments must be acknowledged to the sender. If the sender receives no acknowledgment for a segment after a certain period of time, it will assume the segment was lost and send it again.
Of course, you can add an own frame header on top of every data fragment you sent over UDP, that way your application code can number the sent fragments and you can implement an acknowledgement-resent strategy in your code but the question is: Will this really be better than what TCP is already offering for free? Even if it would be equally good, save yourself the time and just use TCP. A lot of people already thought they can do better than TCP and usually they realize in the end, actually they cannot. TCP has its weaknesses but in general it is pretty good at what it does.