“滑动窗口” - 是否可以为协议增加可靠性并避免流量控制实施?

时间:2009-07-11 03:00:50

标签: c networking tcp network-programming udp

作为个人项目的一部分,我正在制作一个可靠的应用程序级协议(封装在UDP中)。

为了实现可靠性,我必须跟踪我发送的数据包以及在另一个接收端接收的数据包。这是在滑动窗口的帮助下完成的,它还可以保持流量控制。

  1. 除了标准的滑动窗口/流量控制技术之外,还有办法实现可靠性。
  2. 如果不是,有人会分享他的经验/设计理由/代码,并在这篇文章中进行讨论。
  3. 如果是,您是否已实施,或者您知道该概念的任何实施。

7 个答案:

答案 0 :(得分:2)

令人遗憾的是,TCP / IP堆栈不包含可靠的数据报协议,但事实并非如此。您可以搜索大量的尝试和提案。

如果这是一个个人项目,你的时间可能是最稀缺的资源,除非你的目标是重新发明这个特定的轮子,否则只需在TCP之上构建你的协议并继续前进。 / p>

答案 1 :(得分:2)

阅读完所有这些答案后,从其他实施中学习并阅读一些论文,我正在撰写/分享最相关的内容。首先让我谈谈流量控制,稍后我将讨论可靠性。

有两种流量控制 -

  • 基于速率 - 数据包传输及时完成。
  • 基于窗口 - 基于标准窗口,可以是静态或动态(滑动窗口)。

基于速率的流量控制很难实现,因为它们基于RTT(往返时间 - 它不像ping的RTT那么简单)计算。如果您决定提供专有的拥塞控制系统,并且从现有版本开始提供,那么您可以进行基于速率的流量控制。显式拥塞控制也是路由器相关的,所以它没有图片。

基于窗口的流控制,一个窗口用于跟踪所有发送的数据包,直到发送方确定接收方已收到它们。静态窗口很容易实现,但吞吐量很难实现。动态窗口(也称为滑动窗口)是一种更好的实现,但实现起来有点复杂,并且取决于各种类型的确认机制。

现在可靠性......

可靠性确保接收方已收到您的数据包/信息。这意味着接收者必须告诉发送者,是的,我得到了它。此通知机制称为确认。

现在其中一个需要吞吐量来传输数据。因此,您应该能够尽可能多地发送数据包,而不是MAX [发送方的发送限制,接收方的接收限制],前提是您在两端和整个路径都有可用带宽。

如果你结合了所有的知识,虽然可靠性和流量控制是不同的概念,但实现方面,当你使用滑动窗口时,最好实现底层机制。

所以最后简而言之,我和其他任何人如果设计一个新的应用程序协议并需要它可靠,滑动窗口应该是实现它的方法。如果您计划实施拥塞控制,那么您也可以使用混合(基于窗口+速率)方法(uDT)。

答案 2 :(得分:0)

我在这方面与Nik有点同意,听起来你正在使用UDP来完成TCP的工作,可靠的传输和流量控制。但是,有时他们是自己做这件事的理由。

为了回答你的问题,有一些基于UDP的协议可以进行可靠的传输而且不关心排序,这意味着只有丢弃的数据包才能使它到达目的地(通过要求重传)。

我们每天使用的最好的例子是一个名为RADIUS的协议,我们在EVDO网络上用于身份验证和记帐。源和目标之间的每个数据包都获得一个标识符字段(半径仅使用1个字节,您可能需要更多),并且每个标识符都需要被激活。现在Radius并没有真正使用滑动窗口的概念,因为它实际上只是一个控制平面流量,但使用TCP的概念是完全可行的。因此,因为每个数据包都需要被激活,所以你可以缓冲传出数据包的副本,直到它们被远程端点激活,每个人都很高兴。流控制可以使用来自此确认机制的反馈来了解它可以扩展/缩小数据包的速率,这可能最容易通过您传输的数据包的列表大小来控制,但等待确认。

请记住,几乎有数十年的研究使用滑动窗口和调整TCP / IP堆栈周围的数据包丢失和滑动窗口,所以你可能有一些工作,但它可能很难复制在现代操作系统中,你在高度调整的堆栈中得到同样的东西。

这种方法的真正好处是你需要可靠的运输,但你真的不需要订购,因为你发送了不相交的信息。这是TCP / IP发生故障的地方,因为丢弃的数据包会阻止所有数据包进入堆栈,直到重新发送数据包为止。

答案 3 :(得分:0)

您可以使用简单的Send-> Ack协议。对于每个数据包,在使用下一个数据包进行处理之前需要一个Ack(有效的是这是一个windows size = 1数据包 - 我不称之为滑动窗口: - )

答案 4 :(得分:0)

您可以拥有以下内容:

第1部分:初始化

1)发送方发送一个包含要发送的数据包的数据包。该数据包可能需要设置某种控制位或不同的大小,以便接收器可以将其与常规数据包区分开来。

2)接收方向发送方发送ACK。

3)重复步骤1-2,直到Sender收到ACK。

第2部分:发送大量数据

4)发送者然后发送所有包含序列号的数据包附加到数据部分的前面。

5)接收方接收所有数据包并按序列号指定排列。接收器保持数据结构以跟踪已接收的序列号。

第3部分:发送缺失数据

6)在没有收到更多数据包的情况下经过一段超时时间后,接收方会向发送方发送一条消息,要求丢失数据包。

7)发件人将丢失的数据包发送给接收者。

8)重复步骤6-7,直到Receiver收到所有必需的数据包。

9)接收方向发送方发送一个特殊的“完成”数据包。

10)发送者向接收者发送ACK。

11)重复步骤10-11,直到接收方收到ACK。

数据结构 接收器可以通过几种方式跟踪丢失的序列号。最直接的方法是为每个序列号保留一个布尔值,但这将是非常低效的。您可能希望保留丢失数据包范围的列表。例如,如果总共有100个数据包,您将从包含一个元素[(1-100)]的列表开始。每次收到数据包时,只需增加该范围前面的数字即可。假设您成功收到数据包1-12,错过数据包13-14,收到15-44,错过45-46,然后您最终得到类似:[(13-14),(45-46)]。将此数据结构放入数据包并将其发送给发件人将非常容易。你可以通过使用树来改善它,但不确定。

答案 5 :(得分:0)

您可能希望查看SCTP - 它可靠且面向消息。

答案 6 :(得分:-1)

这可能是一种更好的方法来维护UDP应用程序中的本地状态,以检查是否已传输必要的数据以确认可靠性 - 而不是尝试完成数据包级别的可靠性和流量控制。

试图在UDP路径中复制TCP的可靠性和流量控制机制根本不是一个好的答案。