如果TCP数据包得到部分确认,重传机制将如何反应?


12

如果TCP客户端将序列号从10000到20000的数据包发送到TCP服务器。tcp将使用seq_ack 20001进行ACK响应。

如果我拦截了来自客户端的TCP数据包,并将其分成2个tcp段,一个段的seq从10000到15000,另一个段的seq从15001到20000。然后将这2个TCP段发送到TCP服务器。假设第二段在路径中丢失。TCP服务器将使用seq_ack 15001响应ACK。

现在,由于TCP客户端发送了seq 10000到20000的整数数据包,但是从客户端的角度来看,它收到的ACK为15001,这很奇怪。它会如何反应?从理论上讲,客户端应从seq 15001到20000重新传输字节,即,客户端将从seq 15001传输新的数据包。但是,在TCP堆栈实现中,这种做法与理论中的相同吗?

我认为在TCP发送缓冲区中,当发送tcp段时,该段仍然停留在那里直到ACK。ACK到来时,将从缓冲区中清除该段的这些字节。发送缓冲区中有一个指针,当收到ACK时,该指针指向ack_seq所对应的位置。ack_seq以下的字节将被清除。这样,整个段都不需要重新传输吗?

Answers:


8

这称为选择性确认,并且已经包含在RFC 2018中定义的TCP规范中。这将允许客户端确实仅重发15001到20000字节(因为如果按照您说的那样将它们分成不同的包/段,它们位于不同的包/段中),但更有趣的是,它甚至允许无序确认。

从RFC 2018开始:

当接收到包含SACK选项的ACK时,数据发送方应记录选择确认,以备将来参考。假定数据发送方具有重传队列,该重传队列包含按序号顺序已发送但尚未确认的段。

支持SACK不是由TCP规范要求。如果客户端服务器不支持选择性确认,则实际上必须重新传输所有字节10000到20000。

在TCP堆栈实现中,与理论上的相同吗?

通常SACK 可以支持,因为性能,效率和等待时间的增加非常重要-尤其是在像Internet这样的网络中。

但是,的确,即使您按照说明手动操作数据包,这些假设也应成立。根据RFC 793,至少必须重新传输整个数据窗口,但是接收者确实知道接收到的数据至少是有效的。有关实现的详细信息,请参阅第3.3节 -RFC 793中的序列号

有关带有或不带有选择性确认支持的整个过程的概述,请参阅本文(其中包括一些非常有用的图表)。


这对我来说有点奇怪,因为TCP是基于流的,面向字节的协议。为什么要重新传输整个段?在我看来,不带SAKC的TCP是面向段的流协议,而带Sack的TCP是面向字节的。我认为RFC没有对此进行详细说明。
13

TCP堆栈如何管理其发送缓冲区,是否与我在更新的问题中写的内容相同。
2013年

@misteryes 本文概述了该过程(也提供了一些很棒的图表!)。
突破

在您推荐的链接中,作者似乎仍然以面向片段的方式而不是面向字节的方式讨论该问题。是不是
2013年

1
发布此问题之前,我已经知道SACK。从一开始我就认为SACK与这个问题无关。我认为,如果TCP不是面向字节而是面向段,那么SACK也应该相同。启用S​​ACK和禁用SACK的区别在于,使用SACK,TCP允许ack_seq中的序列空洞。但是我认为序列孔对应于一个片段。根据您的说法,孔可以是线段的一半/一部分。
2013年

3

段大小可以(并且确实)在连接的整个生命周期内发生变化。幸运的是,TCP无需记录以前与单个数据包一起发送的段大小。因此,它将执行以下操作:

  1. 每当ACK到达时,将指针相应地前进到第一个未确认的字节,并丢弃任何现在不需要的缓冲区。
  2. 当需要重传时(快速重传或超时;不是在收到第一个ACK之后立即发送!),它将以当前有效的段大小重新发送,从指针到第一个未确认字节。

两种操作都与最初发送这些字节的段大小无关。因此,该理论应与大多数实现相匹配。

让我给出一些背景来解释:

TCP是否使用字节或段?对于应用程序,TCP公开了字节流接口。此外,所有标头字段和内部变量均以字节为单位。但是,为了传输信息,TCP将它们分成段进行分块,因为一对一发送字节会非常浪费:-)。在各处使用字节计数器的优点是,段大小在连接的整个生命周期中无需保持恒定:

  • 引入了一些选项,例如在重传时搭载SACK(如果有的话,实际的实现很少会遇到这种情况)
  • 路径MTU发生变化,例如,沿路径的一个链接更改为较低的MTU或出现瓶颈MTU链接。当建立隧道(VPN,PPPoE)或路由协议选择其他MTU链接时,会发生这种情况。这在设置了“不要片段”的IPv4中发生(对于大多数现代TCP都是如此)。始终在TCPv6中)。

顺便说一句:SACK不是这里的答案,因为接收器(通常)仅在识别出字节流中空洞(即,如果一个数据包丢失但随后的数据包到达)时才使用SACK 。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.