TCP纠错重传
在计算机网络中,大部协议自身并不包含可靠传输数据的机制。他们可能会使用诸如校验和或CRC之类的数学函数来检测到已接收的错误数据,但是他们并不会尝试去修复错误。
使用IP和UDP,根本不会进行错误修复。使用基于以太网和其他协议的协议,该协议提供一定的重试次数,如果无法成功,则放弃。
数据丢失处理
处理数据包丢失(和比特错误)的一种直接方法是重新发送数据包,直到正确接收它为止。这需要一种方法来确定(1)接收方是否已接收到数据包,以及(2)接收到的数据包是否与发送方发送的数据包相同。接收方向发送方发信号通知其已接收到数据包的方法称为确认(ACK)。发送方以其最基本的形式发送数据包并等待ACK。当接收方接收到数据包时,它将发送ACK。当发送方收到ACK时,它将发送另一个数据包,然后继续进行处理。
这里要问的有趣问题是(1)发送方应等待多长时间?(2)如果ACK丢失了怎么办?(3)如果接收到数据包但有错误怎么办?
第一个问题比较有难度,我们需要决定等待多久,它涉及到发送方期待多久能获取到一个接收方的ACK。确定这一点可能很困难,[后续文章会讨论].
问题2的答案更容易:如果丢弃了ACK,发送方就无法轻易将这种情况与原始数据包被丢弃的情况区分开,因此它只是简单地再次发送了数据包。当然,在这种情况下,接收方可能会收到两份或更多份,因此必须准备好处理这种情况。关于第三个问题,通常情况下使用代码的方式更容易仅使用几个比特位(bits)来检测大数据包中的错误,而不是尝试去修正这些错误。
较简单的代码通常无法纠正错误,但可以检测到它们。这就是为什么校验和CRC如此流行的原因。
为了检测数据包中的错误,我们使用一种校验和形式。当接收方收到包含错误的数据包时,它将拒绝发送ACK。最终,发送方重新发送该数据包,一般情况下重发的数据包大概率不会再继续出现错误,当然如果继续有错误,只需要把上面的步骤重新实施一遍即可。
数据包重复
即使使用目前为止介绍的简单方案,接收器也可能会收到正在传输的数据包的重复副本。使用序列号可以解决此问题。基本上,每个唯一的数据包在源处发送时都会获得一个新的序列号,并且此序列号会随数据包本身一起携带。接收者可以使用此号码来确定它是否已经看到该数据包,如果已经看到,则将其丢弃。
吞吐量
TCP目前讨论了其可靠性,但是其效率的问题依然存在。
考虑一下从发送者到接收者甚至传送一个小数据包的时间会发生什么情况(延迟或延迟)很大(例如,一秒或两秒,这对于卫星链路而言并不常见),并且有多个数据包要发送。发送方能够将单个数据包注入到通信路径中,但随后必须停止直到听到ACK。因此,此协议称为“停止并等待”。它的吞吐性能(每单位时间在网络上发送的数据)与M / R成正比,其中M是数据包大小,R是往返时间(RTT),假设在传输过程中没有数据包丢失或受到不可挽回的损害。对于固定大小的数据包,如R上升,吞吐量下降。如果数据包丢失或损坏,情况甚至更糟:“吞吐量”(每单位时间传输的有用数据量)可能大大低于吞吐量。
一次允许一个以上的数据包进入网络会使事情变得非常复杂。现在,发送者不仅必须决定何时将数据包注入网络,还必须决定发送多少。它还必须弄清楚如何在等待ACK时保留计时器,并且必须保留尚未确认的每个数据包的副本,以防需要重传。
接收器需要具有更复杂的ACK机制:一种可以区分已接收和未接收的数据包。
接收器可能需要一种更复杂的缓冲(数据包存储)机制,使该机制可以容纳“失序”数据包(那些由于丢失或重新排序而早于预期的数据包),除非它只是想要丢掉这样的数据包,这是非常低效的。还有其他问题可能并不那么明显。
如果接收器比发送器慢怎么办?
如果发送方只是简单地以很高的速率注入许多数据包,则接收方可能由于处理器或内存限制而丢弃它们?
同样的问题也存在于关于中间的路由器。
如果网络基础结构无法处理发送方和接收方希望使用的数据速率怎么办?
上述问题可以通过引入TCP窗口机制来解决。