TCP协议传输机制作者姓名作者单位正式对外名称,省份城市邮编;摘要:本文简要介绍了TCP协议的特点、可靠传输的实现、流量控制、拥塞控制等关键词:TCP传输流量控制拥塞控制引言TCP:TransmissionControlProtocol传输控制协议。TCP是一种面向连接(连接导向)的、可靠的、基于字节流的运输层(Transportlayer)通信协议,在简化的计算机网络OSI模型中,它完成第四层传输层所指定的功能。1TCP协议的主要特点TCP协议是TCP/IP体系中非常复杂的一个协议,下面先介绍其主要特点。(1)TCP是面向连接的传输层协议。这就是说,应用程序在使用TCP协议之前,必须先建立TCP连接。在传送数据完毕后,必须释放已经建立的TCP连接。(2)每一条TCP连接只能有两个端点,每一条TCP连接只能是点对点的。(3)TCP提供可靠交付的服务。也就是说,通过TCP连接传送的数据,无差错、不丢失、不重复、并且按序到达。(4)TCP提供全双工通信。TCP允许通信双方的应用进程在任何时候都能发送数据。TCP连接的两端都设有发送缓存和接收缓存,用来临时存放双向通信的数据。在发送时,应用程序在把数据传送给TCP的缓存后,就可以做自己的事,而TCP在合适的时候把数据发送出去。在接收时,TCP把收到的数据放入缓存,上层的应用进程在合适的时候读取缓存中的数据。(5)面向字节流。虽然在应用程序和TCP的交互式一次一个数据块,但TCP把应用程序交下来的数据看成仅仅是一连串的无结构的字节流。TCP不保证接收方应用程序所收到的数据块和发送方应用程序所发出的数据块具有对应大小的关系,但接收方应用程序收到的字节流必须和发送方应用程序发出的字节流完全一样。2TCP可靠传输的实现2.1以字节为单位的滑动窗口TCP的滑动窗口是以字节为单位的。假定A收到了B发来的确认报文段,其中窗口是20字节,而确认号是31。根据这两个数据,A就构造出自己的发送窗口。先讨论发送方A的发送窗口。发送窗口表示:在没有收到B确认的情况下,A可以把窗口内的数据都发送出去。凡是已经发送过的数据,在未收到确认之前都必须暂时保留,以便在超时传送中使用。发送窗口里面的序号表示允许发送的序号。窗口越大,发送方就可以在收到对方确认之前连续发送更多的数据,但接收方必须来得及处理这些收到的数据。发送窗口后沿的部分表示已发送且已收到了确认。这些数据显然不需要再保留。而发送窗口前沿的部分表示不允许发送的,因为接收方都没有为这部分数据保留是存放的缓存可空间。发送窗口的位置由窗口前沿和后沿的位置共同确定。发送窗口后沿的变化情况有两种可能,即不动(没有收到新的确认)和前移(收到了新的确认)。发送窗口后沿不可能向后移动,因为不能撤销掉已收到的确认。发送窗口前沿通常是不断向前移动,但也有可能不动。这对应于两种情况:一是没有收到新的确认,对方通知的窗口大小也不便;二是收到了新的确认但对方通知的窗口缩小了,使得发送窗口前沿正好不动。要描述一个发送窗口的状态需要三个指针P1,P2和P3,,指针都指向字节的序列号。这三个指针指向的几个部分的意义如下:小于P1的是已发送并已收到确认的部分,大于P3的是不允许发送的部分。P3-P1=A的发送窗口P2-P1=已发送但尚未收到确认的字节数P3-P2=允许发送但尚未发送的字节数再看一下B的接收窗口。B的接收窗口大小是20。在接收窗口外面,到30号为止的数据是已经发送过确认,并且已经交付给主机了。因此B可以不再保留这些数据。接收窗口内的序号是允许接收的。现在假定B收到了序号为31的数据,并把31到33的数据交付给主机,然后B删除这些数据。接着把接收窗口向前移动3个序号,同时给A发送确认。A收到B的确认后,就可以把发送窗口向前滑动3个序号,但指针P2不动。A在继续发送完后面的数据后,指针P2向前移动和P3重合,发送窗口内的序号都已用完,但还没有再收到确认。由于A的发送窗口已满,可用窗口减小到零,因此必须停止发送。若发送窗口内所有数据都已正确到达B,B也早已发出了确认,但这些确认滞留在网络中。为了保证可靠传输,A只能认为B还没收到这些数据。于是,A在经过一段时间后就重传这部分数据,,,直到收到B的确认位置。如果A收到的确认号落在发送窗口内,A就可以是发送窗口继续向前滑动,并发送新的数据。2.2超时传送时间的选择上面讲到,TCP的发送方在规定时间内没有收到确认解就要重传已发送的报文段。为了使超时重传时间不至于过长或过短,TCP采用了一种自适应算法,它记录一个报文段发出的时间,以及接收到相应的时间,这两个时间差就是报文段的往返时间RTT。TCP保留了RTT的一个加权平均往返时间RTTS。每当第一次测量到RTT样本时,RTTS值就为所测量到的RTT样本值。但以后没测量到一个新的RTT样本,就按下式重新计算一次RTTS:新的RTTS=(1-α)×(旧的RTTS)+α×(新的RTT样本)上式中0≤α<1。显然,超时计时器设置的超时传送时间RTO应略大于上面所得出的加权平均往返时间RTTS。RFC2988建议使用下式计算TRO:RTO=RTTS+4×RTTDRTTD是RTT的偏差的加权平均,它与RTTS和新的RTT样本之差有关。RFC2988建议当第一次测量时RTTD值取为测量到的RTT样本值的一半。在以后的测量中,则使用下式计算加权平均的RTTD:新的RTTD=(1-β)×(旧的RTTD)+β×∣RTTS—新的RTT样本∣这里β是一个小于1的系数,他的推荐值是1.25。2.3选择确认SACK若收到的报文无差错,只是未按照序号,中间还缺少一些序号的数据,那么能否设法只传送缺少的数据而不重传已经确认到达接收方的数据呢?答案是可以的。选择确认就是一种可行的处理方法。现举例说明选择确认的工作原理。TCP的接收方在接受对方发送过来的数据字节流的序号不连续,结果就形成了一些不连续的字节块。比如,接收方收到了前面的的字节流不连续的字节流不连续的两个字节块。如果这些字节的序号都在接收窗口之内,那么接收方就先收下这些数据,但要把这些信息准确告诉发送方,使发送方不要再重复发送这些已收到的数据。我们知道,TCP的首部没有那个字段能够提供字块的信息边界信息。RFC2018规定,如果要选择确认,那么在建立TCP连接时,就要在TCP首部的现象中加上“允许SACK”的选项,而双方必须都事先商定好。如果使用选择确认,那么原来首部中的“确认号字段”的用法不便。只是以后再TCP报文段的首部中都增加了SACK选项,以便报告收到的不连续的字节块的边界。然而,SACK文档并没有指明发送方应当怎样相应SACK。因此大多数的实现还是重传所有未被确认的数据块。3TCP的流量控制一般来说,我们只是希望数据传输得更快一些。但如果发送方把数据发送得过快,接收方就有可能来不及接收,这就会造成数据的丢失。所谓流量控制就是让发送方速率不要太快,要让接收方来得及接收。3.1利用滑动窗口实现流量控制TCP滑动窗口技术通过动态改变窗口大小来调节两台主机间数据传输。每个TCP/IP主机支持全双工数据传输,因此TCP有两个滑动窗口:一个用于接收数据,另一个用于发送数据。TCP使用肯定确认技术,其确认号指的是下一个所期待的字节。假定发送方设备以每一次三个数据包的方式发送数据,也就是说,窗口大小为3。发送方发送序列号为1、2、3的三个数据包,接收方设备成功接收数据包,用序列号4确认。发送方设备收到确认,继续以窗口大小3发送数据。当接收方设备要求降低或者增大网络流量时,可以对窗口大小进行减小或者增加,本例降低窗口大小为2,每一次发送两个数据包。当接收方设备要求窗口大小为0,表明接收方已经接收了全部数据,或者接收方应用程序没有时间读取数据,要求暂停发送。发送方接收到携带窗口号为0的确认,停止这一方向的数据传输。滑动窗口机制为端到端设备间的数据传输提供了可靠的流量控制机制。然而,它只能在源端设备和目的端设备起作用,当网络中间设备(例如路由器等)发生拥塞时,滑动窗口机制将不起作用。4TCP的拥塞控制在计算机网络中的链路容量(即宽带)、交换节点中的缓存和处理机等,都是网络的资源。若在某段时间对网络中某一资源的需求超过了该资源所能提供的可用部分,网络的性能就要变坏。这种情况叫做拥塞。拥塞控制就是防止过多的数据注入到网络中,这样可以使网络中的路由器或链路不至于过载。下面介绍几种常用的拥塞控制方法。4.1拥塞避免算法拥塞避免算法是一种处理丢失分组的方法。该算法假定由于分组受到损坏引起的丢失是非常少的(远小于1%),因此分组丢失就意味着在源主机和目的主机之间的某处网络上发生了拥塞。有两种分组丢失的指示:发生超时和接收到重复的确认。拥塞避免算法和慢启动算法是两个目的不同、独立的算法。但是当拥塞发生时,我们希望降低分组进入网络的传输速率,于是可以调用慢启动来作到这一点。在实际中这两个算法通常在一起实现。拥塞避免算法和慢启动算法需要对每个连接维持两个变量:一个拥塞窗口cwnd和一个慢启动门限ssthresh。这样得到的算法的工作过程如下:1)对一个给定的连接,初始化cwnd为1个报文段,ssthresh为65535个字节。2)TCP输出例程的输出不能超过cwnd和接收方通告窗口的大小。拥塞避免是发送方使用的流量控制,而通告窗口则是接收方进行的流量控制。前者是发送方感受到的网络拥塞的估计,而后者则与接收方在该连接上的可用缓存大小有关。3)当拥塞发生时(超时或收到重复确认),ssthresh被设置为当前窗口大小的一半(cwnd和接收方通告窗口大小的最小值,但最少为2个报文段)。此外,如果是超时引起了拥塞,则cwnd被设置为1个报文段(这就是慢启动)。4)当新的数据被对方确认时,就增加cwnd,但增加的方法依赖于我们是否正在进行慢启动或拥塞避免。如果cwnd小于或等于ssthresh,则正在进行慢启动,否则正在进行拥塞避免。慢启动一直持续到我们回到当拥塞发生时所处位置的半时候才停止(因为我们记录了在步骤2中给我们制造麻烦的窗口大小的一半),然后转为执行拥塞避免。慢启动算法初始设置cwnd为1个报文段,此后每收到一个确认就加1。这会使窗口按指数方式增长:发送1个报文段,然后是2个,接着是4个……。拥塞避免算法要求每次收到一个确认时将cwnd增加1/cwnd。与慢启动的指数增加比起来,这是一种加性增长(additiveincrease)。我们希望在一个往返时间内最多为cwnd增加1个报文段(不管在这个RTT中收到了多少个ACK),然而慢启动将根据这个往返时间中所收到的确认的个数增加cwnd。假定当cwnd为32个报文段时就会发生拥塞。于是设置ssthresh为16个报文段,而cwnd为1个报文段。在时刻0发送了一个报文段,并假定在时刻1接收到它的ACK,此时cwnd增加为2。接着发送了2个报文段,并假定在时刻2接收到它们的ACK,于是cwnd增加为4(对每个ACK增加1次)。这种指数增加算法一直进行到在时刻3和4之间收到8个ACK后cwnd等于ssthresh时才停止,从该时刻起,cwnd以线性方式增加,在每个往返时间内最多增加1个报文段。术语“慢启动”并不完全正确,它只是采用了比引起拥塞更慢些的分组传输速率,但在慢启动期间进入网络的分组数增加的速率仍然是在增加的。只有在达到ssthresh拥塞避免算法起作用时,这种增加的速率才会慢下来。4.2快速重传与快速恢复算法在收到一个失序的报文段时,TCP立即需要产生一个ACK(一个重复的ACK)。这个重复的ACK不应该被迟延。该重复的ACK的目的在于让对方知道收到一个失序的报文段,并告诉对方自己希望收到的序号。由于我们不知道一个重复的ACK是由一个丢失的报文段引起的,还是由于仅仅出现了几个报文段的重新排序,因此我们等待少量重复的ACK到来。假如这只是一些报文段的重新排序,则在重新排序的报文段被处理并产生一个新的ACK之前,只可能产生1~2个重复的ACK。如果一连串收到3个或3个以上的重复ACK,就非常可能是一个报文段丢失了。于是我们就重传