TCP数据传输协议(二)

来源:互联网 发布:java 一个对象的大小 编辑:程序博客网 时间:2024/05/21 01:48

TCP的数据编号与确认

TCP协议是面向字节的。TCP把应用层交下来的长报文(这可能要划分为许多较短的报文段)看成是一个个字节组成的数据流,并使每一个字节对应一个序号。在连接建立的时,双方TCP要商定初始的序号。TCP每一次发送的报文段首部中的序号字段表示该报文段数据部分的第一个自己对应得序号。

TCP发送的确认是指对所有按序接受到的数据的确认。但接收方返回的确认号是已按序号排列的数据字节对应的最大序号加1.也就是说,确认号 表示接收方期望下次收到的数据中的第一个字节对应的序号。

TCP传输的可靠是由于使用了序号和确认。当TCP发送一报文段时,它同时也在自己的重传队列中存放一个副本,如果确认对方收到了该报文段,则删除这个副本。若在计时器时间到之前未收到确认,则重传此报文段的副本。需要注意的是,TCP并不保证此报文段已由应用层交付给了端用户,而只是确认接收方的TCP已经接收到了对方传输的数据。

由于TCP连接能提供全双工通信,因此通信两端没有必要专门发送确认报文段,而可以在传送数据的时候顺便把确认信息发送过去,这样可以提高传输效率

在发送方,TCP是怎样决定发送一个报文段的时机呢?

TCP有三种基本机制来控制报文段的发送。第一种机制是TCP维持一个变量,它等于最大报文长度MSS,只要发送缓存从发送进程得到的数据达到MSS字节时,就组装成一个报文段将其发送。第二种,发送方的应用进程指明要求发送的报文段,即TCP支持的推送操作。第三种,发送方的一个计时器期限到了,这时就把当前已有的缓存数据装入报文段发送出去。

另外存在一个问题叫做糊涂窗口综合症。接收方的缓存已满,而交互式的应用程序一次只会从接受缓存中读取一个字节的数据。然后接收方向发送方发送确认,并将窗口设置为1字节。接着,发送方又发送来一个字节(但是发来的IP数据报是41个字节)。接收方发回确认,仍然 将窗口设置为1个字节。这样进行下去,会使网络的效率变得很低。

要解决这个问题,可以让接收方等待一段时间,使得或者缓存已经能有足够的空间容纳一个最长的报文段,或者缓存已有一半的空间处于空的状态。只要出现这两种情况之一,接收方就发出确认报文,并向发送方通知当前的窗口大小。此外。发送方 也不要发送太小的报文段,而是把数据积累的足够大,或达到接收方缓存空间的一般大小。

上述两种办法可以配合使用。使得在发送方不发送很小的报文段的同时,接受方也不要在缓存刚刚有了一点空位置就立马告诉发送方。

TCP的流量控制与拥塞控制

1.滑动窗口的概念

为了提高报文段的传输效率。TCP采用可改变大小的滑动窗口模式进行流量控制。窗口大小的单位是字节。在TCP报文段首部的窗口字段写入的值就是当前给对方设置的发送窗口数值的上限。

发送窗口在建立的时候由双方商定,但是在接受过程中,接收方可以随时根据自己的实际情况改变窗口的大小。



如上图8-12所示,要发送900字节长的数据,我们将他划分为9个100字节长的报文段,而发送窗口设定的为500字节。发送方只要收到对方的确认,发送框就可以前移 。发送TCP要维护一个指针,每发送一个报文段,指针就向前移动一个报文段的距离。当指针移动到发送窗口的最右端时就不能发送报文段,

8-13中,ACK表示首部中的ACK,小写的ack表示确认收到的字段的值。

利用发送窗口调节发送方向网路注入分组的速率不仅仅是为了使接收方来得及接受,而且还是对网络进行拥塞控制。拥塞发生在网络传输的分组数量接近网络对分组的处理能力的时候,所以需要将网络的分组维持到一定的水平之下。运输层的报文段就是网络层分组的数据部分。

2。慢开始和拥塞避免

根据以上所述,发送方的主机在确定发送报文段的速率时,既要根据接收方的能力,还要从全局来考虑不要使网络发生拥塞。因此,对于每一个TCP,需要有以下两个状态的变量。

(1)接收方窗口rwnd,这时接收方根据自己目前的接受缓存大小所许诺的最新窗口值,是来接受方的流量控制。接收方将此窗口值放在tcp报文的首部中的窗口字段,传送给发送方。接收方窗口又成为通知窗口。

(2)拥塞窗口cwnd,这时发送方自己估计的网络拥塞成都而设置的窗口值,是来自发送方的流量控制。

发送方流量控制的原则应该是这样:当网络没有发生拥塞的时候,就将窗口变大,以便把更多的分组发送出去;当网络发生拥塞时,又将窗口缩小,以减少注入到网络中的分组数。

发送放如果没有收到确认报文ACK,则就认为网络出现了拥塞。

总之,发送窗口的上限值=Min{rwnd,cwnd}

慢开始的原理是:当主机开始发送数据的时候,如果立即把较大的发送窗口中的所有数据, 全部发出去往往会容易造成网络拥塞。经验证明,较好的方法是先试探性的发送,由小到大逐渐增大发送方的拥塞窗口数值。一般在刚开始发送报文段的时候,将cwnd设置为一个最大报文段MSS的数值,如果未发生阻塞,则在下一次发送中 再增加一个MSS值。用这样的方法逐步增加发送方的拥塞窗口cwnd,可以使分组注入网络的速度更合理。

下面用例子来说明慢开始的算法原理。为说明原理的方便起见,我们用报文段的个数作为窗口值的大小,并且假定接收方的rwnd足够大,因此发送窗口只受发送方的拥塞阻塞cwnd控制。


在连接建立的开始,设定cwnd=1,发送第一个报文段M0,接收方收到之后发回确认ACK1(表示期待下一次收到M1)。发送方在收到ACK1后,把cwnd增大为2,发送M1,M2,接收方收到后发回确认ACK2和ACK3,因为发送方没收到一个ACK就让cwnd的值加1,所以发送方在收到ACK2和ACK3后,会使得cwnd的值增加2,即在下一次发送时cwnd的值为4,即一次性发送4个报文段。由此可见,慢开始的“慢”并不是真的慢,他是成几何式增长的。只是在开始的时候将cwnd=1,使用慢开始算法可以使发送方在开始发送时间向网络注入的分组数量大大减少,这对防止网络拥塞是个非常有利的措施。

但同时,为了防止cwnd的快速增长引起网路拥塞,还需要另一个状态变量,即慢开始门限ssthresh。慢开始门限ssthresh的用法如下:

当cwnd<ssthresh时,使用慢开始算法。

当cwdn>ssthresh时,停止使用慢开始算法,改用拥塞避免算法。

当cwdn=ssthresh时,既可使用慢开始算法,也可以使用拥塞避免算法。

拥塞避免算法使用方法是使发送方的拥塞窗口cwnd每经过一个往返时延RTT就增加一个MSS值(而不管在RTT时间里收到了多少个ACK),这样拥塞窗口cwnd按线性规律缓慢增加,比慢开始增加的速率缓慢很多。

无论在慢开始阶段还是拥塞避免阶段,只要出现网络拥塞(其根据就是没有按时收到ACK或收到了重复的ACK),就要将慢开始门限ssthresh设置为出现网络拥塞时发送窗口值(即接收方窗口和拥塞窗口中较小的一个)的一半(但不能小于2).这样设置的考虑就是:既然出现了网络拥塞,那就要减少注入网络的分组数。然后将拥塞窗口cwnd设置为1,并执行慢开始算法。这样做的目的就是要迅速减少主机发送到网络中的分组数,使得发生拥塞的路由器有足够的时间把队列中积压的分组处理完毕。

下图说明了上述拥塞控制的具体过程。(单位是报文段)

(1)当TCP连接进行初始化时,将拥塞窗口置为1,慢开始门限的初始值设置为16个报文段,我们在此假定接收方的接收窗口rwnd足够大,所以现在的发送窗口的数值等于拥塞窗口的数值。

(2)在执行慢算法时,拥塞窗口的初始值为1,以后每收到一个对新报文段确认的ack,就将发送方的拥塞窗口加1,然后再开始下一轮传输。一个轮次就是把拥塞窗口cwdn所允许的报文段都发送出去,并且都收到了对方的确认。一个轮次的时间不是固定不变的。因此拥塞窗口随着传输次数按指数规律增长。当拥塞窗口cwnd增长到慢开始门限值ssthresh的时候改为用拥塞避免算法。拥塞窗口按线性规律增长。


(3)假定拥塞窗口到24时发生了网络超时(即网络拥塞)。更新后的ssthresh值变成了12,即为发生拥塞时cwdn值得一般,拥塞窗口再重新设定为1,并执行慢开始算法。当cwdn=12时又开始执行拥塞避免算法。

另外,我们常说的“乘法减小”和“加法增大”。“乘法减小”是指不论在慢开始阶段还是拥塞避免阶段,只要出现网络阻塞,就立即将ssthresh值减半,这样在网络频繁出现阻塞时,ssthresh值就下降的很快,以大大减少注入到网络中的分组数。“加法增大”是指执行拥塞避免算法之后,当收到对所有报文段的确认就将拥塞窗口值加1个MSS值,是拥塞窗口值缓慢增大,以防止网络过早出现拥塞。

3。快重传和快恢复

上面所说的两个算法是在TCP中最早使用的拥塞控制算法。但后来人们发现这种拥塞控制算法还需要改进,因为有时一条TCP连接会因为等待重传计时器的超时而空闲较长的时间,为此又增加了两个新的拥塞控制算法。这就是快重传和快恢复。

如下图所示


假定了,发送方要发送M1到M4共4个报文段。接收方每收到一个报文段就立马要发送确认ACK,而不要等待自己发送数据时才将ACK捎带上。如图所示,在发送M1和M2时正常,但发送M3时丢失了,此后不管接收方收到的M4M5,接受方都会重复发送确认ACK3,当发送方连续4次收到确认ACK3时就 立即 重发M3,而不用等待超时计时器的时间。这就是快重传算法,它并不是取消重传计时器,而是尽早重传丢失的报文段

与快重传配合使用的还有块恢复算法。当不使用快恢复算法时,发送方若是发现网络出现拥塞就会将拥塞窗口降为1,然后执行慢开始算发。但这样做的缺点就是网络不能很快地恢复到正常状态。快恢复算法剋较好的解决这一个问题:

(1)当发送方收到连续三个重复ACK的时候,就重新按照上面所说的“乘法减小”,重新设置慢开始门限ssthresh。

(2)与慢开始不同之处的是他的拥塞窗口不是设置为1,而是ssthresh+3*MSS。这样做是因为,发送方收到3个ACK3,这就表明有三个组已经离开了网络,他们不会再消耗网络的资源,这三个分组是停留在接收方的缓存之中。可见现在网络中不是堆积了分组而是少了3个分组。因此,将拥塞窗口扩大些并不会加剧网络的阻塞。

(3)若收到的重复ACK为n个,则将cwnd设置为ssthresh+n*MSS.

(4)若发送窗口值还允许发送报文段,就按照拥塞避免算法继续发送报文段。

(5)若收到了确认新的报文段的ACK,就将cwnd缩小到ssthresh


原创粉丝点击