
TCPIP详解学习笔记(11-13).doc
8页TCP/IP详解学习笔记(11)-TCP交互数据流,成块数据流目前建立在TCP协议上的网络协议特别多,有telnet,ssh,有ftp,有http等等这些协议又可以根据数据吞吐量来大致分成两大类:(1)交互数据类型,例如telnet,ssh,这种类型的协议在大多数情况下只是做小流量的数据交换,比如说按一下键盘,回显一些文字等等2)数据成块类型,例如ftp,这种类型的协议要求TCP能尽量的运载数据,把数据的吞吐量做到最大,并尽可能的提高效率针对这两种情况,TCP给出了两种不同的策略来进行数据传输1.TCP的交互数据流对于交互性要求比较高的应用,TCP给出两个策略来提高发送效率和减低网络负担:(1)捎带ACK2)Nagle算法(一次尽量多的发数据)通常,在网络速度很快的情况下,比如用lo接口进行telnet通信,当按下字母键并要求回显的时候,客户端和服务器将经历发送按键数据->服务器发送按键数据的ack -> 服务器端发送回显数据->客户端发送回显数据的ACK的过程,而其中的数据流量将是40bit + 41bit+41bit+40bit = 162bit,如果在广域网里面,这种小分组的TCP流量将会造成很大的网络负担。
1.1.捎带ACK的发送方式这个策略是说,当主机收到远程主机的TCP数据报之后,通常不马上发送ACK数据报,而是等上一个短暂的时间,如果这段时间里面主机还有发送到远程主机的TCP数据报,那么就把这个ACK数据报“捎带”着发送出去,把本来两个TCP数据报整合成一个发送一般的,这个时间是200ms可以明显地看到这个策略可以把TCP数据报的利用率提高很多1.2.Nagle算法上过bbs的人应该都会有感受,就是在网络慢的时候发贴,有时键入一串字符串以后,经过一段时间,客户端“发疯”一样突然回显出很多内容,就好像数据一下子传过来了一样,这就是Nagle算法的作用Nagle算法是说,当主机A给主机B发送了一个TCP数据报并进入等待主机B的ACK数据报的状态时,TCP的输出缓冲区里面只能有一个TCP数据报,并且,这个数据报不断地收集后来的数据,整合成一个大的数据报,等到B主机的ACK包一到,就把这些数据“一股脑”的发送出去虽然这样的描述有些不准确,但还算形象和易于理解,我们同样可以体会到这个策略对于低减网络负担的好处在编写插口程序的时候,可以通过TCP_NODELAY来关闭这个算法并且,使用这个算法看情况的,比如基于TCP的X窗口协议,如果处理鼠标事件时还是用这个算法,那么“延迟”可就非常大了。
2.TCP的成块数据流对于FTP这样对于数据吞吐量有较高要求的要求,将总是希望每次尽量多的发送数据到对方主机,就算是有点“延迟”也无所谓TCP也提供了一整套的策略来支持这样的需求TCP协议中有16个bit表示“窗口”的大小,这是这些策略的核心2.1.传输数据时ACK的问题在解释滑动窗口前,需要看看ACK的应答策略,一般来说,发送端发送一个TCP数据报,那么接收端就应该发送一个ACK数据报但是事实上却不是这样,发送端将会连续发送数据尽量填满接受方的缓冲区,而接受方对这些数据只要发送一个ACK报文来回应就可以了,这就是ACK的累积特性,这个特性大大减少了发送端和接收端的负担2.2.滑动窗口滑动窗口本质上是描述接受方的TCP数据报缓冲区大小的数据,发送方根据这个数据来计算自己最多能发送多长的数据如果发送方收到接受方的窗口大小为0的TCP数据报,那么发送方将停止发送数据,等到接受方发送窗口大小不为0的数据报的到来书中的P211和P212很好的解释了这一点关于滑动窗口协议,书上还介绍了三个术语,分别是:1. 窗口合拢:当窗口从左边向右边靠近的时候,这种现象发生在数据被发送和确认的时候2. 窗口张开:当窗口的右边沿向右边移动的时候,这种现象发生在接受端处理了数据以后。
3. 窗口收缩:当窗口的右边沿向左边移动的时候,这种现象不常发生TCP就是用这个窗口,慢慢的从数据的左边移动到右边,把处于窗口范围内的数据发送出去(但不用发送所有,只是处于窗口内的数据可以发送这就是窗口的意义图20-6解释了这一点窗口的大小是可以通过socket来制定的,4096并不是最理想的窗口大小,而16384则可以使吞吐量大大的增加2.3.数据拥塞上面的策略用于局域网内传输还可以,但是用在广域网中就可能会出现问题,最大的问题就是当传输时出现了瓶颈(比如说一定要经过一个slip低速链路)所产生的大量数据堵塞问题(拥塞),为了解决这个问题,TCP发送方需要确认连接双方的线路的数据最大吞吐量是多少这,就是所谓的拥塞窗口拥塞窗口的原理很简单,TCP发送方首先发送一个数据报,然后等待对方的回应,得到回应后就把这个窗口的大小加倍,然后连续发送两个数据报,等到对方回应以后,再把这个窗口加倍(先是2的指数倍,到一定程度后就变成现行增长,这就是所谓的慢启动),发送更多的数据报,直到出现超时错误,这样,发送端就了解到了通信双方的线路承载能力,也就确定了拥塞窗口的大小,发送方就用这个拥塞窗口的大小发送数据。
要观察这个现象是非常容易的,我们一般在下载数据的时候,速度都是慢慢“冲起来的”以上就是TCP数据传输的大致流程,虽然并不细致,但是足以描述TCP的工作原理,重点是TCP的流量控制原理,滑动窗口,拥塞窗口,ACK累计确认等知识点TCP/IP详解学习笔记(12)-TCP的超时与重传超时重传是TCP协议保证数据可靠性的另一个重要机制,其原理是在发送某一个数据以后就开启一个计时器,在一定时间内如果没有得到发送的数据报的ACK报文,那么就重新发送数据,直到发送成功为止1.超时超时时间的计算是超时的核心部分,TCP要求这个算法能大致估计出当前的网络状况,虽然这确实很困难要求精确的原因有两个:(1)定时长久会造成网络利用率不高2)定时太短会造成多次重传,使得网络阻塞所以,书中给出了一套经验公式,和其他的保证计时器准确的措施1.1.递推公式概说最早的TCP曾经用了一个非常简单的公式来估计当前网络的状况,如下R<-aR+(1-a)MRTP=Rb其中a是一个经验系数为0.1,b通常为2注意,这是经验,没有推导过程,这个数值是可以被修改的这个公式是说用旧的RTT(R)和新的RTT(M)综合到一起来考虑新的RTT(R)的大小。
但是,我们又看到,这种估计在网络变化很大的情况下完全不能做出“灵敏的反应”(Jacoboson说的,不是偶说的,呵呵),于是就有下面的修正公式:Err=M-AA<-A+gErrD<-D+h(|Err|-D)RTO=A+4D具体的解释请看书的228页,这个递推公式甚至把方差这种统计概念也使用了进来,使得偏差更加的小而且,必须要指出的是,这两组公式更新,都是在数据成功传输的情况下才进行,在发生数据重新传输的情况下,并不使用上面的公式进行网络估计,理由很简单,因为程序已经不在正常状态下了,估计出来的数据也是没有意义的1.2.RTO的初始化RTO的初始化是由公式决定的,例如最初的公式,初始的值应该是1而修正公式,初始RTO应该是A+4D1.3.RTO的更新当数据正常传输的情况下,我们就会用上面的公式来更新各个数据,并重开定时器,来保证下一个数据被顺利传输要注意的是:重传的情况下,RTO不用上面的公式计算,而采用一种叫做“指数退避”的方式例如:当RTO为1S的情况下,发生了数据重传,我们就用RTO=2S的定时器来重新传输数据,下一次用4S一直增加到64S为止1.4.估计器的初始化在这里,SYN用的估计器初始化似乎和传输用的估计器不一样(我也没有把握)造我的理解,在修正公式中,SYN的情况下,A初始化为0,D初始化为3S。
而在得到传输第一个数据的ACK的时候,应该按照下面的公式进行初始化:A=M+0.5D=A/21.5.估计器的更新和上面的讨论差不多,就是在正常情况下,用上面的公式计算,在重传的情况下,不更新估计器的各种参数原因还是因为估计不准确1.6.Karn算法这不算是一个算法,这应该是一个策略,说的就是更新RTO和估计器的值的时机选择问题,1.3.和1.5.所说得更新时机就是Karn算法1.7.计时器的使用两句话:1. 一个连接中,有且仅有一个测量定时器被使用也就是说,如果TCP连续发出3组数据,只有一组数据会被测量2. ACK数据报不会被测量,原因很简单,没有ACK的ACK回应可以供结束定时器测量2.重传有了超时就要有重传,但是就算是重传也是有策略的,而不是将数据简单的发送2.1.重传时发送数据的大小前面曾经提到过,数据在传输的时候不能只使用一个窗口协议,我们还需要有一个拥塞窗口来控制数据的流量,使得数据不会一下子都跑到网路中引起“拥塞”也曾经提到过,拥塞窗口最初使用指数增长的速度来增加自身的窗口,直到发生超时重传,再进行一次微调但是没有提到,如何进行微调,拥塞避免算法和慢启动门限就是为此而生所谓的慢启动门限就是说,当拥塞窗口超过这个门限的时候,就使用拥塞避免算法,而在门限以内就采用慢启动算法。
所以这个标准才叫做门限,通常,拥塞窗口记做cwnd,慢启动门限记做ssthresh下面我们来看看拥塞避免和慢启动是怎么一起工作的算法概要(直接从书中拷贝)1. 对一个给定的连接,初始化cwnd为1个报文段,ssthresh为65535个字节2. TCP输出例程的输出不能超过cwnd和接收方通告窗口的大小拥塞避免是发送方使用 的流量控制,而通告窗口则是接收方进行的流量控制前者是发送方感受到的网络拥塞的估 计,而后者则与接收方在该连接上的可用缓存大小有关3. 当拥塞发生时(超时或收到重复确认),ssthresh被设置为当前窗口大小的一半(cwnd 和接收方通告窗口大小的最小值,但最少为2个报文段)此外,如果是超时引起了拥塞,则 cwnd被设置为1个报文段(这就是慢启动)4. 当新的数据被对方确认时,就增加cwnd,但增加的方法依赖于我们是否正在进行慢启 动或拥塞避免如果cwnd小于或等于ssthresh,则正在进行慢启动,否则正在进行拥塞避免 慢启动一直持续到我们回到当拥塞发生时所处位置的半时候才停止(因为我们记录了在步骤2 中给我们制造麻烦的窗口大小的一半),然后转为执行拥塞避免补充上面的拥塞避免公式在P238页。
这整个的流程让我联想到开车换档的过程2.2.快速重传和快速恢复算法这是数据丢包的情况下给出的一种修补机制一般来说,重传发生在超时之后,但是如果发送端接受到3个以上的重复ACK的情况下,就应该意识到,数据丢了,需要重新传递这个机制是不需要等到重传定时器溢出的,所以叫做快速重传,而重新传递以后,因为走的不是慢启动而是拥塞避免算法,所以这又叫做快速恢复算法流程如下:1. 当收到第3个重复的ACK时,将ssthresh设置为当前拥塞窗口cwnd的一半重传丢失的 报文段设置cwnd为ssthresh加上3倍的报文段大小2. 每次收到另一个重复的ACK时, cwnd增加1个报文段大小并发送1个分组(如果新的 cwnd允许发送)3. 当下一个确认新数据的ACK到达时,设置cwnd为ssthresh(在第1步中设置的值)这个 ACK应该是在进行重传后的一个往返时间内对步骤1中重传的确认另外,这个ACK也应该 是对丢失的分组和收到的第1个重复的ACK之间的所有中间报文段的确认这一步采用的是拥 塞避免,因为当分组丢失时我们将当前的速率减半2.3.ICMP会引起重新传递么?答案是:不会,TCP会坚持用自己的定时器,但是TCP会保留下ICMP的错误并且通知用户。
