TCP可靠传输和拥塞控制机制
TCP可靠传输
数据流传输方式
TCP数据一般分为:交互数据和成块数据,交互数据一般比较小,比如发送一个字节的交互数据,加上TCP数据段首部以及IP数据包首部,至少需要41个字节。
交互数据流传输
互联网早期通信链路并不可靠,因此在链路层传输数据的时候要采取可靠的传输协议。其中最简单的为停止等待协议。传输层并不使用停止等待协议,但是传输交互数据流传输时采用nagle算法和该协议原理很类似。
停止等待协议
每一次发送完一个分组就停止发送,等待对方确认。
发送放发送数据分组A,接收方接收到A后,向发送方确认数据,发送方收到A确认后继续发送数据分组B。
数组分组在传输过程中发生错误时有两种情况:
- 接收方收到错误数据直接丢弃
- 数据分组在传输过程中丢失
这两种情况接收方都不会发送任何信息。发送方在一定时间内没有收到确认就会重传,这种叫超时重传。
nagle算法
在传输交互数据流一般用nagle算法。nagle算法要求在一个TCP连接上最多只能有一个未被确认的小分组。在该分组确认到达之前不能发送其他分组。
在收到确认之后并不是立刻发送其他分组,TCP连接允许不存在数据分组。具体的nagle算法规则如下:
- 缓存中数据长度达到最大报文长度时,允许 发送。
- 缓存中数据长度达到发送窗口一半时,允许发送。
- 报文首部FIN标志为1的时候允许发送。
- 报文段首部设置了TCP_NODELAY选项,则允许发送。
- 发生了超时,立即发送。
成块数据流传输
成块数据流往往超过最大报文长度,要进行拆分之后再发送,交互数据碎片化的问题不会出现。成块数据是通过基于滑动窗口协议的连续ARQ协议完成的。
滑动窗口协议
使用基于停止等待协议的nagle算法信道利用率太低。
如果使用流水线传输,那么信到利用率会大幅提升,TCP采用滑动窗口协议来实现流水线传输。
滑动窗户协议是指数据发送方有一个发送窗口,发送窗口范围内的数据允许发送,随着接收方传来的确认信息以及通知的接收窗口的大小来动态调整发送窗口的起始位置以及大小。
窗口有三种情况:
- 前沿向右移动,这种情况在数据发送并且被确认时
- 后沿向右移动,允许发送更多数据。发生于接收窗口增大或者网络拥塞情况缓解。
- 后沿向左移动,发生于接收方希望窗口缩小。
TCP要求接收方有累计确认功能,接收方不必立刻对收到的数据进行确认,这样可以减少传输开销。另外,在发送确认时也可以捎带上接收方要发送的数据。TCP标准规定确认推迟的时间不能超过0.5秒,如果收到一个具有最大报文长度的报文段,则必须隔一个报文段就发送一个确认。
累计确认只针对按序到达的最后一个分组发送确认。表示这个分组已经全部到达。
比如上图中序号5、6、7、9、10分组到达接收方,接收方发送的确认序号是8,即接收方没有收到序号8的分组,希望下次收到序号8的分组。而序号9、10分组虽然已经到达的事实,发送方并不知晓。
这会导致一个问题:一旦发生超时重传的情况,发送方是否需要再次发送已经到达的数据?如果不需要,又该如何获知具体哪些数据已经到达?
后退N帧ARQ协议
发生超时重传时,后退N帧ARQ协议不考虑确认序号之后的分组是否已经发送到接收方,直接从确认序号开始重传之后的数据。
选择重传ARQ协议
选择重传指接收方收到未按序排列的数据流时,通知发送方重传缺失的数据,而不是重传全部的数据。
SR中窗口的大小必须小于等于分组序号的一半,不然很容易和新的分组混淆,接受法无法判断新传来的数据分组到底是上一个分组的数据还是新的分组的数据。
比如上图,收到了三个不连续的分组,这时候在TCP首部选项中加入”允许SACK“选项。在之后的TCP报文段增加SACK选项。
超时重传时间
对于每一个连接,TCP管理4个不同的定时器:
- 重传定时器:决定何时重传未被确认的数据分组
- 坚持定时器:使窗口的大小信息保持不变
- 保活定时器:检测i空闲连接的另一端是否崩溃或重启
- 2MSL定时器:测量一个连接处于TIME_WAIT状态时间
在超时重传的情况下,如果将超时重传的时间设置的太短,会出现很多不必要的重传,增大网络负荷;如果设置的时间太长,则使网络的空闲时间增大,降低传输效率。TCP采用一种自适应的算法来动态计算超时重传的时间。
报文段往返时间
一个报文段发出的时间和收到确认的时间差就是报文段的往返时间RTT。平滑的往返时间RTT_S是RTT的加权平均值。
Karn算法
发送报文段后,在一定时间内没有收到确认。重传该报文段,之后收到确认报文。那么怎么确定确认报文是对哪个报文的确认?因为重传的报文和原报文完全相同,收到的确认报文也相同。那么报文段往返时间RTT是A还是B呢?
在上述情况下,Karn提出一个算法:在计算加权平均RTT_S时,只要报文段重传了,就不采用其往返时间样本。这样的到的加权平均RTT_S和RTO就比较准确。
可靠数据传输机制及其用途的总结
机制 | 用途 |
---|---|
检验和 | 用于检测在一个传输分组中的比特错误 |
定时器 | 用于检测超时/重传一个分组,因为该分组(或者ACK)在信道中丢失了。由于当一个分组延时但未丢失,或者一个分组已经被接收方收到但从接收方到发送方的ACK丢失时,可能产生超时事件,所以接收方可能会收到一个分组的多个冗余拷贝 |
序号 | 用于为发送方流向接收方的数据分组按顺序编号。所接收分组的序号间的空隙可使该接收方检测出丢失的分组。具有相同序号的分组可是接受方检测出一个分组的冗余拷贝。 |
确认 | 接收方告知发送方分组被正确接受。确认报文通常携带被确认分组或者多个分组序号,确认可以是逐个或者累计的,取决于协议。 |
否定确认 | 接收方用于告知发送方某个分组未被正确的接收,否定确认报文通常携带者未被正确接收的分组的序号 |
窗口 | 发送方被限制仅发送指定范围内序号的分组。通过允许一次发送多个分组但未被确认。 |
TCP流量控制
流量控制
一条TCP连接的双方主机都为该连接设置了接收缓存,当该TCP连接接收正确,按序的字节后,它就将数据放入接收缓存。如果发送方发送数据太快而接收方读取速度缓慢,很容易使得缓存溢出。TCP为应用程序提供了 流量控制服务,来匹配接收方和发送法的速率。
TCP通过让发送方维护一个接收窗口的变量来提供流量控制,用于告诉发送方接收方还有多少缓存。
发送方轮流跟踪两个变量LastByteSent(最后一个发送序号)和LastByteAcked(最后一个确认序号),这两个变量的差值就是发送方到接收方之间未被确认的数据量,将未被确认的数据量控制在窗口大小以内就可以保证接收方缓存不会溢出。
流量控制死锁避免
当发送者收到一个窗口为0的应答,发送者便停止发送,等待接受者下一个应答,但是如果这个时候一个窗口不为0的应答在传输过程中丢失,发送者一直等待,而接受者认为发送者收到应答,也等待接受新数据,这样就产生了死锁。
为了避免这样的情况,TCP使用了持续计数器,每当发送者收到一个零窗口的应答就启动计时器,时间一到就主动询问接收方窗口大小。若接收者仍然返回零窗口,则重置该计时器继续等待;若窗口不为0,则表示应答报文丢失了,此时重置发送窗口后开始发送,这样就避免了死锁的产生。
TCP拥塞控制
拥塞控制和流量控制的区别
拥塞控制:作用于网络 ,防止过多的数据注入到网络中,避免网络负载过大的情况
流量控制:流量控制作用于接受者,控制发送者的发送速度从而使得接受者来得及接收,防止分组丢失。
端到端拥塞控制
在端到端拥塞控制方法中,网络层没有为运输层拥塞控制显式支持。
TCP采用的方法就是让每一个发送方根据所感知到的网络拥塞程度来限制其向连接发送流量的速率。这需要解决三个问题
- TCP如何限制发送流量速率
- TCP如何感受网络的拥塞程度
- TCP采用什么算法来控制发送的速率
为了解决第一个问题,TCP定义了一个变量CongWin(拥塞窗口),一个发送方的未被确认的数据为Math.min(RcvWindow, Congwindow)。
假设接受缓存足够大的情况下,未被确认数据量大小仅和ConWin有关,因此这个拥塞窗口的值就限制了发送方未被确认的数据量,因此间接的限制了发送方的发送速率。粗略考虑就是在一个RTT的时间内,发送方允许向该连接发送最多CongWin个字节数据。
下面考虑第二个问题,TCP如何感知网络中是否出现拥塞。
我们定义一个TCP发送方的丢包事件:要么出现超时,要么收到来自接受方的三个冗余ACK。因为网络中过度拥塞时,网络中路由器的缓存会溢出,导致TCP数据包被丢弃。丢弃数据包就会引发(超时或者冗余ACK)。
拥塞控制算法
TCP感知到网络中的拥塞后,TCP要实现调节发送速率的算法,主要分为慢开始,拥塞避免,快重传,快恢复
慢开始算法
发送方维持拥塞窗口ConWin的变量,慢开始算法的思路就是不要一开始就发送大量的数据,先探测一下网路的拥塞程度,具体步骤如下
- 初始化拥塞窗口的大小为1,表示可以传送一个MSS大小的数据(MSS:最大报文长度)
- 每次接受一个ACK,ConWIn大小加1
- 每当过了一个往返时延RTT,ConWin大小直接翻倍
- 当ConWin达到预先设置的阈值ssthresh时或者发生丢包事件,进入拥塞避免算法
拥塞避免算法
收到ACK时,线性增长ConWin
当网络出现丢包(收到重复的ACK或者超时)时,更新阈值ssthresh为原来的一半
快重传算法
- 快速重传算法要求接收方收到一个失序的报文段之后就立即发出重复确认而不需要等到自己发送数据时捎带确认,一旦收到三个重复确认的ACK就立即重传而不需要等待超时计时器到期。
快恢复算法
配合快重传算法,当发送方收到连续三个重复的ACK,就执行乘法减小算法,把ssthresh门限减半,但是接下去并不执行满开始算法。
考虑网络拥塞就不会收到好几个重复的确认,发送方认为网络没有出现拥塞,此时不执行慢开始算法,而是执行拥塞避免算法。
注意:在采用快恢复算法时,慢开始算法只是在TCP连接建立时和网络出现超时时才使用。
参考文献
《计算机网络-自顶向下方法(原书第四版)》