1、TCP传输的机制 周昕炜 (武汉大学,湖北省 武汉市 430072 学号2010302590022) 摘要:本文简要介绍了TCP协议的特点、可靠传输的实现、流量控制、拥塞控制等 关键词:TCP 传输 流量控制 拥塞控制 1 TCP协议的主要特点 TCP协议是TCP/IP体系中非常复杂的一个协议,下面先介绍其主要特点。TCP是一种面向连接的、可靠的传输层协议;TCP协议建立在不可靠的网络层IP协议之上,IP不能提供任何可靠性机制,TCP的可靠性完全由自己实现;TCP采用的最基本的可靠性技术有 确认与超时重传和流量控制。 2 TCP可靠传输的实现 2.1 以字节为单位的滑
2、动窗口 TCP 采用大小可变的滑动窗口进行流量控制。窗口大小的单位是字节。 在 TCP 报文段首部的窗口字段写入的数值就是当前给对方设置的发送窗口数值的上限。发送窗口在连接建立时由双方商定。但在通信的过程中,接收端可根据自己的资源情况,随时动态地调整对方的发送窗口上限值(可增大或减小)。 情况(a): 发送端要发送 900 字节长的数据,划分为 9 个 100 字节长的报文段,而发送窗口确定为 500 字节。发送端只要收到了对方的确认,发送窗口就可前移。发送 TCP 要维护一个指针。每发送一个报文段,指针就向前移动一个报文段的距离。 情况(b): 发送端已发送了 400 字节的数据
3、但只收到对前 200 字节数据的确认,同时窗口大小不变。现在发送端还可发送 300 字节。 情况(c): 发送端收到了对方对前 400 字节数据的确认,但对方通知发送端必须把窗口减小到 400 字节。现在发送端最多还可发送 400 字节的数据。 发送窗口里面的序号表示允许发送的序号。窗口越大,发送方就可以在收到对方确认之前连续发送更多的数据,但接收方必须来得及处理这些收到的数据。 发送窗口后沿的部分表示已发送且已收到了确认。这些数据显然不需要再保留。而发送窗口前沿的部分表示不允许发送的,因为接收方都没有为这部分数据保留是存放的缓存可空间。 发送窗口的位置由窗口前沿和后沿的位置共
4、同确定。发送窗口后沿的变化情况有两种可能,即不动(没有收到新的确认)和前移(收到了新的确认)。发送窗口后沿不可能向后移动,因为不能撤销掉已收到的确认。发送窗口前沿通常是不断向前移动,但也有可能不动。这对应于两种情况:一是没有收到新的确认,对方通知的窗口大小也不便;二是收到了新的确认但对方通知的窗口缩小了,使得发送窗口前沿正好不动。 要描述一个发送窗口的状态需要三个指针P1,P2和P3,,指针都指向字节的序列号。这三个指针指向的几个部分的意义如下: 小于P1的是已发送并已收到确认的部分,大于P3的是不允许发送的部分。 P3-P1=A的发送窗口 P2-P1=已发送但尚未收到确认的字节数
5、P3-P2=允许发送但尚未发送的字节数 再看一下B的接收窗口。B的接收窗口大小是20。在接收窗口外面,到30号为止的数据是已经发送过确认,并且已经交付给主机了。因此B可以不再保留这些数据。接收窗口内的序号是允许接收的。 现在假定B收到了序号为31的数据,并把31到33的数据交付给主机,然后B删除这些数据。接着把接收窗口向前移动3个序号,同时给A发送确认。A收到B的确认后,就可以把发送窗口向前滑动3个序号,但指针P2不动。 A在继续发送完后面的数据后,指针P2向前移动和P3重合,发送窗口内的序号都已用完,但还没有再收到确认。由于A的发送窗口已满,可用窗口减小到零,因此必须停止发送。若发送窗
6、口内所有数据都已正确到达B,B也早已发出了确认,但这些确认滞留在网络中。为了保证可靠传输,A只能认为B还没收到这些数据。于是,A在经过一段时间后就重传这部分数据,,,直到收到B的确认位置。如果A收到的确认号落在发送窗口内,A就可以是发送窗口继续向前滑动,并发送新的数据。 2.2 超时传送时间的选择 上面讲到,TCP的发送方在规定时间内没有收到确认解就要重传已发送的报文段。为了使超时重传时间不至于过长或过短,TCP采用了一种自适应算法,它记录一个报文段发出的时间,以及接收到相应的时间,这两个时间差就是报文段的往返时间RTT。TCP保留了RTT的一个加权平均往返时间RTTS。每当第一次测量到R
7、TT样本时,RTTS值就为所测量到的RTT样本值。但以后没测量到一个新的RTT样本,就按下式重新计算一次RTTS: 新的RTTS=(1-α)×(旧的RTTS)+α×(新的RTT样本) 上式中0≤α<1。显然,超时计时器设置的超时传送时间RTO应略大于上面所得出的加权平均往返时间RTTS。RFC2988建议使用下式计算TRO: RTO=RTTS+4×RTTD RTTD是RTT的偏差的加权平均,它与RTTS和新的RTT样本之差有关。RFC2988建议当第一次测量时RTTD值取为测量到的RTT样本值的一半。在以后的测量中,则使用下式计算加权平均的RTTD: 新的RTTD=(1-β)×(旧的
8、RTTD)+β×∣RTTS—新的RTT样本∣ 这里β是一个小于1的系数,他的推荐值是1.25。 2.3 选择确认SACK 若收到的报文无差错,只是未按照序号,中间还缺少一些序号的数据,那么能否设法只传送缺少的数据而不重传已经确认到达接收方的数据呢?答案是可以的。选择确认就是一种可行的处理方法。 现举例说明选择确认的工作原理。TCP的接收方在接受对方发送过来的数据字节流的序号不连续,结果就形成了一些不连续的字节块。比如,接收方收到了前面的的字节流不连续的字节流不连续的两个字节块。如果这些字节的序号都在接收窗口之内,那么接收方就先收下这些数据,但要把这些信息准确告诉发送方,使发送方不要再重
9、复发送这些已收到的数据。我们知道,TCP的首部没有那个字段能够提供字块的信息边界信息。RFC2018规定,如果要选择确认,那么在建立TCP连接时,就要在TCP首部的现象中加上“允许SACK”的选项,而双方必须都事先商定好。如果使用选择确认,那么原来首部中的“确认号字段”的用法不便。只是以后再TCP报文段的首部中都增加了SACK选项,以便报告收到的不连续的字节块的边界。 然而,SACK文档并没有指明发送方应当怎样相应SACK。因此大多数的实现还是重传所有未被确认的数据块。 3 TCP的流量控制 TCP采用大小可变的滑动窗口机制实现流量控制功能。窗口的大小是字节。在TCP报文段首部的窗口字段
10、写入的数值就是当前给对方设置发送窗口的数据的上限。 在数据传输过程中,TCP提供了一种基于滑动窗口协议的流量控制机制,用接收端接收能力(缓冲区的容量)的大小来控制发送端发送的数据量。 在建立连接时,通信双方使用SYN报文段或ACK报文段中的窗口字段捎带着各自的接收窗口尺寸,即通知对方从而确定对方发送窗口的上限。在数据传输过程中,发送方按接收方通知的窗口尺寸和序号发送一定量的数据,接收方根据接收缓冲区的使用情况动态调整接收窗口尺寸,并在发送TCP报文段或确认段时稍带新的窗口尺寸和确认号通知发送方。 如图所示。设主机A向主机B发送数据。双方确定的的窗口值是400。设一个报文段为1
11、00字节长,序号的初始值为1(即SEQ=1)。在图15.8中,主机B进行了三次流量控制。第一次将窗口减小为300字节,第二次将窗口又减为200字节,最后一次减至零,即不允许对方再发送数据了。这种暂停状态将持续到主机B重新发出一个新的窗口值为止。 3.1 利用滑动窗口实现流量控制 TCP滑动窗口技术通过动态改变窗口大小来调节两台主机间数据传输。每个TCP/IP主机支持全双工数据传输,因此TCP有两个滑动窗口:一个用于接收数据,另一个用于发送数据。TCP使用肯定确认技术,其确认号指的是下一个所期待的字节。 假定发送方设备以每一次三个数据包的方式发送数据,也就是说,窗口大小为3。
12、发送方发送序列号为1、2、3的三个数据包,接收方设备成功接收数据包,用序列号4确认。发送方设备收到确认,继续以窗口大小3发送数据。当接收方设备要求降低或者增大网络流量时,可以对窗口大小进行减小或者增加,本例降低窗口大小为2,每一次发送两个数据包。当接收方设备要求窗口大小为0,表明接收方已经接收了全部数据,或者接收方应用程序没有时间读取数据,要求暂停发送。发送方接收到携带窗口号为0的确认,停止这一方向的数据传输。 滑动窗口机制为端到端设备间的数据传输提供了可靠的流量控制机制。然而,它只能在源端设备和目的端设备起作用,当网络中间设备(例如路由器等)发生拥塞时,滑动窗口机制将不起作用。
13、4 TCP 的拥塞控制 在计算机网络中的链路容量(即宽带)、交换节点中的缓存和处理机等,都是网络的资源。若在某段时间对网络中某一资源的需求超过了该资源所能提供的可用部分,网络的性能就要变坏。这种情况叫做拥塞。 拥塞控制就是防止过多的数据注入到网络中,这样可以使网络中的路由器或链路不至于过载。 下面介绍几种常用的拥塞控制方法。 4.1 拥塞避免算法 拥塞避免算法是一种处理丢失分组的方法。该算法假定由于分组受到损坏引起的丢失是非常少的(远小于1 %),因此分组丢失就意味着在源主机和目的主机之间的某处网络上发生了拥塞。有两种分组丢失的指示:发生超时和接收到重复的确认。 拥塞避免算法和
14、慢启动算法是两个目的不同、独立的算法。但是当拥塞发生时,我们希望降低分组进入网络的传输速率,于是可以调用慢启动来作到这一点。在实际中这两个算法通常在一起实现。拥塞避免算法和慢启动算法需要对每个连接维持两个变量:一个拥塞窗口c w n d和一个慢启动门限s s t h re s h。这样得到的算法的工作过程如下: (1) 对一个给定的连接,初始化c w n d为1个报文段, s s t h re s h为6 5 5 3 5个字节。 (2)TCP输出例程的输出不能超过c w n d和接收方通告窗口的大小。拥塞避免是发送方使用的流量控制,而通告窗口则是接收方进行的流量控制。前者是发送方感受到
15、的网络拥塞的估计,而后者则与接收方在该连接上的可用缓存大小有关。 (3) 当拥塞发生时(超时或收到重复确认),s s t h re s h被设置为当前窗口大小的一半( c w n d和接收方通告窗口大小的最小值,但最少为2个报文段)。此外,如果是超时引起了拥塞,则c w n d被设置为1个报文段(这就是慢启动)。 (4) 当新的数据被对方确认时,就增加c w n d,但增加的方法依赖于我们是否正在进行慢启动或拥塞避免。如果c w n d小于或等于s s t h re s h,则正在进行慢启动,否则正在进行拥塞避免。慢启动一直持续到我们回到当拥塞发生时所处位置的半时候才停止(因为我们记录
16、了在步骤2中给我们制造麻烦的窗口大小的一半),然后转为执行拥塞避免。 慢启动算法初始设置c w n d为1个报文段,此后每收到一个确认就加1。这会使窗口按指数方式增长:发送1个报文段,然后是2个,接着是4个……。 拥塞避免算法要求每次收到一个确认时将c w n d增加1 /c w n d。与慢启动的指数增加比起来,这是一种加性增长(additive increase)。我们希望在一个往返时间内最多为c w n d增加1个报文段(不管在这个RT T中收到了多少个A C K),然而慢启动将根据这个往返时间中所收到的确认的个数增加c w n d。 假定当c w n d为3 2个报文段时就
17、会发生拥塞。于是设置s s t h re s h为1 6个报文段,而c w n d为1个报文段。在时刻0发送了一个报文段,并假定在时刻1接收到它的A C K,此时c w n d增加为2。接着发送了2个报文段,并假定在时刻2接收到它们的A C K,于是c w n d增加为4(对每个A C K增加1次)。这种指数增加算法一直进行到在时刻3和4之间收到8个A C K后c w n d等于s s t h re s h时才停止,从该时刻起, c w n d以线性方式增加,在每个往返时间内最多增加1个报文段。 术语“慢启动”并不完全正确,它只是采用了比引起拥塞更慢些的分组传输速率,但在慢启动期间进入网络
18、的分组数增加的速率仍然是在增加的。只有在达到s s t h re s h拥塞避免算法起作用时,这种增加的速率才会慢下来。 4.2 快速重传与快速恢复算法 在收到一个失序的报文段时, T C P立即需要产生一个A C K(一个重复的A C K)。这个重复的A C K不应该被迟延。该重复的A C K的目的在于让对方知道收到一个失序的报文段,并告诉对方自己希望收到的序号。 由于我们不知道一个重复的A C K是由一个丢失的报文段引起的,还是由于仅仅出现了几个报文段的重新排序,因此我们等待少量重复的A C K到来。假如这只是一些报文段的重新排序,则在重新排序的报文段被处理并产生一个新的A
19、C K之前,只可能产生1 ~ 2个重复的A C K。如果一连串收到3个或3个以上的重复A C K,就非常可能是一个报文段丢失了。于是我们就重传丢失的数据报文段,而无需等待超时定时器溢出。这就是快速重传算法。接下来执行的不是慢启动算法而是拥塞避免算法。这就是快速恢复算法。 没有执行慢启动的原因是由于收到重复的A C K不仅仅告诉我们一个分组丢失了。由于接收方只有在收到另一个报文段时才会产生重复的A C K,而该报文段已经离开了网络并进入了接收方的缓存。也就是说,在收发两端之间仍然有流动的数据,而我们不想执行慢启动来突然减少数据流。这个算法通常按如下过程进行实现: (1) 当收到第3个重复
20、的A C K时,将s s t h re s h设置为当前拥塞窗口c w n d的一半。重传丢失的报文段。设置c w n d为s s t h re s h加上3倍的报文段大小。 (2) 每次收到另一个重复的A C K时, c w n d增加1个报文段大小并发送1个分组(如果新的c w n d允许发送)。 (3) 当下一个确认新数据的A C K到达时,设置c w n d为s s t h re s h(在第1步中设置的值)。这个A C K应该是在进行重传后的一个往返时间内对步骤1中重传的确认。另外,这个A C K也应该是对丢失的分组和收到的第1个重复的A C K之间的所有中间报文段的确认。这
21、一步采用的是拥塞避免,因为当分组丢失时我们将当前的速率减半。 5 TCP 报文段的格式 TCP的协议数据单元被称为报文段(Segment),TCP通过报文段的交互来建立连接、传输数据、发出确认、进行差错控制、流量控制及关闭连接。报文段分为两部分,即报文段头和数据,所谓报文段头就是TCP为了实现端到端可靠传输所加上的控制信息,而数据则是指由高层即应用层来的数据。 TCP不是按传送的报文段来编号。TCP将所要传送的整个报文(这可能包括许多个报文段)看成是一个个字节组成的数据流,然后对每一个数据流编一个序号。在连接建立时,双方要商定初始序号。TCP就将每一次所传送的报文段中的第一个数据
22、字节的序号,放在 TCP首部的序号字段中。 TCP的确认是对接收到的数据的最高序号(即收到的数据流中的最后一个序号)表示确认。但返回的确认序号是已收到的数据的最高序号加1。也就是说,确认序号表示期望下次收到的第一个数据字节的序号。 由于TCP能提供全双工通信,因此通信中的每一方都不必专门发送确认报文段,而可以在传送数据时顺便把确认信息捎带传送。 若发送方在规定的设置时间内没有收到确认,就要将未被确认的报文段重新发送。接收方若收到有差错的报文段,则丢弃此报文段而并不发送否认信息。若收到重复的报文段,也要将其丢弃,但要发回(或捎带发回)确认信息。这与数据链路层的情况相似。
23、 6 TCP 连接的建立 6.1 建立连接 在源主机想和目的主机通信时,目的主机必须同意,否则TCP连接无法建立。为了建立一个TCP连接,两个系统需要同步其初始TCP序号ISN。序号用于跟踪通信顺序并确保多个包传输时没有丢失。初始序号是TCP连接建立时的起始编号。为了确保TCP连接的成功建立,TCP采用了一种称为三次握手的方式,三次握手方式使得“序号/确认号”系统能够正常工作,从而使它们的序号达成同步。如果三次握手成功,则连接建立成功,可以开始传送数据信息。 其三次握手分别为: 第一步:源主机A的TCP向主机B发出连接请求报文段,其首部中的SYN(同步)标志位
24、应置为1,表示想与目标主机B进行通信,并发送一个同步序列号X(例:SEQ=100)进行同步,表明在后面传送数据时的第一个数据字节的序号是X+1(即101)。SYN同步报文会指明客户端使用的端口以及TCP连接的初始序号。 第二步:目标主机B的TCP收到连接请求报文段后,如同意,则发回确认。在确认报中应将ACK位和SYN位置1,表示客户端的请求被接受。确认号应为X+1(图15.5中为101),同时也为自己选择一个序号Y。 第三步:源主机A的TCP收到目标主机B的确认后要向目标主机B给出确认,其ACK置1,确认号为Y+1,而自己的序号为X+1。TCP的标准规定,SYN置1的报文段要消耗掉
25、一个序号。 运行客户进程的源主机A的TCP通知上层应用进程,连接已经建立。当源主机A向目标主机B发送第一个数据报文段时,其序号仍为X+1,因为前一个确认报文段并不消耗序号。 当运行服务进程的目标主机B的TCP收到源主机A的确认后,也通知其上层应用进程,连接已经建立。至此建立了一个全双工的连接。 6.2 传送数据 位于TCP/IP分层模型的较上层的应用程序传输数据流给TCP。TCP接收到字节流并且把它们分解成段。假如数据流不能被分成一段,那么每一个其它段都被分给一个序列号。在目的主机端.这个序列号用来把接收到的段重新排序成原来的数据流。 (1) 主机A使用滑动窗口
26、发送全部的四个段到主机B。这是第一步。不幸的是,只有段l03、105和106成功地到达了生机B(参看②)。 (2) 因为段103和104是连续的,所以主机B返回一个确认给主机A,通知主机A它只成功地接收到了第103段,在它的确认中主机B使用它期待得到的下一个序列号作为确认(参看③通过给出序列号104)。 (3) 主机A接到主机B的报文后,重新发送段104、105和106(参看④)。虽然主机B已经成功地收到了段105和106,但是根据协议规定,也必须重新发送。 (4) 当主机2成功地收到这些段以后.主机B返回一个确认给主机A(参看⑥),并根据序列号把它们重组成原来的数流。把它传输到高层应用程序。 参考文献: 【1】 谢希仁.计算机网络 北京:电子工业出版社,2011






