通过 UDP 实现 ack?
我们有一个系统(用 C 语言构建)通过 UDP 执行通信。最近我们发现有必要保证数据包的交付。我的问题是:为了确保使用 ack 数据包进行传送,对基于 UDP 的系统最少要添加哪些内容?此外,理想情况下无需操作数据包标头。我们对数据包进行应用程序级别的控制,包括序列号和 ack/nack 标志。我想知道这是否是一个失败的原因,我们尝试做的任何事情基本上都会是一个有缺陷和损坏的 TCP 版本。基本上,我们是否可以进行最小化的改进来实现有保证的交付(我们不需要 TCP 的许多功能,例如拥塞控制等)。谢谢!
We have a system (built in C) in place that performs communication over UDP. Recently we have found a necessity to guarantee delivery of packets. My question is: what would be the minimum additions to a UDP based system to ensure delivery using ack packets? Also, ideally without having to manipulate the packet headers. We have application level control over the packets including sequence numbers and ack/nack flags. I am wondering if this is a lost cause and anything we attempt to do will basically be a flawed and broken version of TCP. Basically, is there a minimalist improvement we can make to achieve guaranteed delivery (we do not need many features of TCP such as congestion control etc.). Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
TCP 交织 3 个可能相关的服务(好吧,TCP 可以做更多的事情,但我只讨论 3 个。)
你刚才说你不需要流量控制,所以我甚至不会解决这个问题(你如何宣传窗口大小等,除了你可能需要一个窗口。我会解决它。)
你确实说过你需要可靠的交付。这并不太难 - 您可以使用 ACK 来表明发送方已收到数据包。基本的可靠传输如下所示:
这三个步骤没有解决以下问题:
因此,对于您的应用程序,您说您只需要可靠的交付 - 但没有说需要按顺序进行。这将影响您实施协议的方式。
(顺序无关紧要的示例:您将员工记录从一台计算机复制到另一台计算机。如果 Alice 的记录先于 Bob 的记录收到,只要两者都到达那里就没有关系。)
因此,假设您只需要可靠(因为这就是您在帖子中所说的),您可以通过多种方式实现这一点。
您的发送者可以跟踪未确认的数据包。因此,如果它发送#3、4、5和6,并且没有收到3和4的ACK,则发送方知道它需要重传。 (虽然发送方不知道数据包 3 和 4 是否很多,或者它们的 ACK 是否丢失。无论哪种方式,我们都必须重新传输。)
但是您的发送方可以执行累积 ACK - 所以在上面的示例中,它只会如果接收到了 3、4 和 5,则确认 #6。这意味着如果接收方之前没有收到过数据包 6,则将丢弃数据包。如果您的网络非常可靠,那么这可能是一个不错的选择。
然而,上述协议确实有一个窗口 - 即发送方一次发送多少个数据包?这意味着您确实需要某种窗口,但不是为了流量控制的目的。您将如何传输窗口大小?
您可以在没有窗口的情况下通过使窗口大小恒定或执行诸如停止并等待之类的操作来完成此操作。前者可能是更好的选择。
不管怎样,我没有直接回答你的问题,但我希望我已经指出了一些在构建这个时值得考虑的事情。在没有流量控制部分(如窗口)并且不考虑顺序的情况下进行“可靠传输”的任务是困难的! (让我知道我是否应该提供有关其中一些内容的更多详细信息!)
祝你好运!
TCP intertwines 3 services that might be relevant (okay TCP does a lot more, but I'm only going to talk about 3.)
You just said that you don't need flow control, so I won't even address that (how you would advertise a window size, etc. well, except that you'll probably need a window. i'll get to it.)
You did say that you need reliable delivery. That isn't too hard - you use ACKs to show that the sender has received a packet. Basic reliable delivery looks like:
Those three steps don't address these issues:
So for your application, you said you only needed reliable delivery - but didn't say anything about needing them in order. This will affect the way you implement your protocol.
(example where in-order doesn't matter: you're copying employee records from one computer to another. doesn't matter if Alice's record is received before Bob's, as long as both get there.)
So going on the presumption that you only need reliable (since that's what you said in your post), you could achieve this several ways.
Your sender can keep track of unacknowledged packets. So if it sends # 3, 4, 5, and 6, and doesn't get an ACK for 3 and 4, then the sender knows that it needs to retransmit. (Though the sender doesn't know if packets 3 and 4 were lots, or if their ACKs were lost. Either way, we have to retransmit.)
But then your sender could do cumulative ACKs - so in the above example, it would only ack #6 if it had received 3, 4, and 5. This means that the receiver would drop packet 6 if it hadn't received the ones before. If your network is very reliable, then this might not be a bad option.
The protocols described above, however, do have a window - that is, how many packets does the sender send at once? Which means that you do need some sort of windowing, but not for the purpose of flow control. How'll you transmit window sizes?
You could do it without a window by either having the window size constant, or by doing something like stop-and-wait. The former might be a better option.
Anyway, I haven't directly answered your question, but I hope I've pointed out some of the things that are worth considering when architecting this. The task of having "reliable transfer" without parts of flow control (like windowing) and without any regard to in-order is hard! (Let me know if I should give more details about some of this stuff!)
Good luck!
请参阅 Steven 的 UNIX Network Programming,第 1 卷 的第 8 章和第 20 章。他涵盖了许多不同的方法。第 20.5 节“为 UDP 应用程序添加可靠性”可能是您最感兴趣的部分。
Take a look at Chapter 8 and Chapter 20 of Steven's UNIX Network Programming, volume 1. He covers a number of different approaches. Section 20.5 "Adding Reliability to a UDP Application" is probably most interesting to you.
我在此处运行一个问题,正在收集答案到“当您需要可靠的 UDP 时应该使用什么”。答案可能比您想要或需要的多得多,但您也许可以查看一些基于 UDP 构建的协议,并仅获取您需要的 ACK 部分。
根据我使用 ENet 协议(一种可靠的 UDP 协议)的工作,我希望您在每个 UDP 数据报中都需要一个序列号,一种为您收到的数据报发送 ACK 的方法,一种保存您收到的数据报的方法。已经发送,直到您收到它们的 ACK 或它们超时,以及一种计时重新发送尚未收到 ACK 的数据报的方法...我还会添加一个总体超时,用于当您决定永远不会将传递一个特定的数据报,并且我想,一个回调到您的应用程序层以通知它传递失败......
I have a question running here which is collecting answers to "What to you use when you need reliable UDP". The answers are possibly much more than you want or need but you might be able to take a look at some of the protocols that have been built on UDP and grab just the ACK part that you need.
From my work with the ENet protocol (a reliable UDP protocol), I expect that you need a sequence number in each UDP datagram, a way of sending an ACK for datagrams that you've received, a way of keeping hold of datagrams that you've sent until you get an ACK for them or they time out and a way of timing the resending of datagrams for which you have yet to receive an ACK... I would also add an overall timeout for when you decide that you are never going to deliver a particular datagram, and, I guess, a callback to your application layer to inform it of this failure to deliver...
实现ack的最好方法是在应用层进行。 CoAP 是在 udp 上运行但提供可靠数据传输的应用程序协议的示例。它为所有可确认(CON)消息保留一个消息ID,并向接收者发送具有相同消息ID的ACK数据包。所有的ack和message id字段都保存在应用层部分。因此,如果发送方没有收到他发送的带有消息 ID 的 Ack 数据包,则会重新传输该数据包。应用程序开发人员可以修改协议以满足可靠数据传输的需要。
The best way to implement ack is to do it in the application layer. CoAP is an example of an application protocol which runs on udp but provides reliable data transfer. It keeps a message id for all the Confirmable(CON) messages and sends an receiver sends an ack packet with the same message id. All the ack and message id fields are kept at the application layer part. So if the sender doesn't receive an Ack packet with the message id send by him, it re transmits that packet. Application developer can modify the protocol to suit the needs required for reliable data transfer .
棘手的问题。我想说,你将无法实现 TCP 的可靠性。然而,我确实明白,有时,您需要可靠的 UDP。
游戏开发论坛
RUDP(更硬核)
有关可靠 UDP 的旧线程
Tough problem. I would say, you wont be able to achieve the reliability of TCP. However, i do understand that sometimes, you need to have reliable UDP.
Gamedev forum
RUDP (a bit more hardcore)
Old Thread about reliable UDP