在UDP中实现ACK机制?

9
我们有一个使用C语言构建的系统,用于执行UDP通信。最近,我们发现需要保证数据包的传递。我的问题是:在不必更改数据包头部的情况下,基于UDP的系统需要添加哪些最小的内容以确保使用ack数据包进行传递?我们可以控制应用程序级别的数据包,包括序列号和ack/nack标志。我想知道是否这是个无望的事情,我们尝试做的任何事情基本上都是TCP的缺陷和错误版本。基本上,我们能做出什么最简单的改进来实现保证传递(我们不需要TCP的许多功能,如拥塞控制等)。谢谢!

2
你确定这值得吗?使用经过验证的技术是否比自制系统更好?性能优势明显还是你只是过早地进行了优化? - Mehrdad Afshari
该系统是实时的,并已符合要求使用UDP协议的规范。 - ron
5个回答

11
TCP交织了3种可能相关的服务(好吧,TCP做了很多事情,但我只谈论3个):
1.按顺序传送 2.可靠传送 3.流量控制
您刚才说不需要流量控制,所以我甚至不会涉及它(如何广告窗口大小等等,好吧,除了您可能需要一个窗口。我会讲到它。)
您确实说您需要可靠传递。这不太难-您使用ACK来显示发送方已接收数据包。基本可靠传递看起来像:
1.发送方发送数据包。 2.接收方接收数据包,然后发送ack。 3.如果发送者没有收到ack(通过计时器),则重新发送数据包。
这三个步骤并未解决以下问题:
1.ACK丢失怎么办? 2.数据包乱序怎么办?
因此,对于您的应用程序,您说只需要可靠传递-但没有提到需要按顺序传递。这将影响您实现协议的方式。
(无需按顺序的示例:您要将员工记录从一台计算机复制到另一台计算机。Alice的记录在Bob之前接收到并不重要,只要两者都到达即可。)
因此,在假设您只需要可靠性(因为这是您在帖子中说的)的情况下,您可以通过几种方式实现此目标。
您的发送方可以跟踪未确认的数据包。因此,如果它发送#3、4、5和6,并且没有收到3和4的ACK,则发送方知道它需要重新传输(尽管发送方不知道数据包3和4是丢失还是它们的ACK丢失了。无论哪种方式,我们都必须重新传输。)

然而,你的发送方可以做累积确认 - 因此在上面的示例中,仅当发送方收到3、4和5时,它才会确认#6。这意味着如果接收方没有收到前面的包,它将丢弃包6。如果您的网络非常可靠,则可能不是一个坏选择。

然而,上述描述的协议确实有一个窗口 - 即发送方一次发送多少个数据包?这意味着您确实需要某种形式的分窗机制,但不是为了流控制的目的。您将如何传输窗口大小?

您可以通过使窗口大小恒定或执行类似于停止和等待的操作来实现无需窗口的传输。前者可能是更好的选择。

总之,我没有直接回答您的问题,但我希望我已指出了一些在设计时值得考虑的事情。在没有任何与顺序相关的流控制(例如分窗)且不考虑按顺序传输的情况下实现“可靠传输”的任务很难!(让我知道是否应该提供有关某些内容的更多详细信息!)

祝你好运!


5

请查看Steven的UNIX网络编程卷1的第8章和第20章。他涵盖了许多不同的方法。第20.5节“向UDP应用程序添加可靠性”可能对您最有兴趣。


+1 作为一个很好的参考。之前在编程作业中做类似的事情时,那一部分非常棒。 - mrduclaw

4

我有一个问题正在这里收集关于“当需要可靠的UDP时你会使用什么”的答案。这些答案可能比你想要或需要的更多,但你可以看一些已经基于UDP构建的协议,并抓取你需要的ACK部分。

从我使用ENet协议(一种可靠的UDP协议)的经验来看,我认为每个UDP数据报中都需要一个序列号,一种发送已接收数据报的ACK的方式,一种保留已发送数据报直到你收到ACK或它们超时的方法以及定时重新发送尚未收到ACK的数据报的方法... 我还会添加一个总体超时时间,用于决定你永远无法传递特定数据报的情况,并且,我猜测,回调你的应用层以通知它无法传递此数据报的失败...


1

实现确认应答的最佳方式是在应用层中进行。CoAP是一个应用协议的例子,它运行在UDP上但提供可靠的数据传输。它为所有的Confirmable(CON)消息保留一个消息ID,并发送一个带有相同消息ID的确认包。所有确认和消息ID字段都保存在应用程序层部分。因此,如果发送者没有收到带有他发送的消息ID的Ack包,它将重新发送该数据包。应用程序开发人员可以修改协议以满足所需的可靠数据传输。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接