# 【学习笔记】计算机网络 谢希仁版(五)运输层(重点) > 教材:计算机网络(第七版)谢希仁版 # 运输层  ## 1. 网络进程间的通信,端口号,套接字,在网络上唯一标识一个进程 > 从通信和信息处理的角度看,运输层向它上面的应用层提供通信服务,它属于面向通信部分的最高层,同时也是用户功能中的最底层。 这里要注意一点: 从运输层的角度看,通信的真正端点并不是主机而是主机中的进程,也就是说,端到端的通信应用进程之间的通信。 运输层提供应用进程间的逻辑通信。好像这种通信就是沿水平方向直接传送数据。但事实上这两个运输层之间并没有一条水平方向的物理连接。  从上图可以看出,网络层为主机之间提供逻辑通信,而运输层为应用进程之间提供端到端的逻辑通信。此外,运输层还要对收到的报文进行差错检测。 ## 2. UDP 与 TCP 运输层需要有两种不同的运输协议,面向连接的TCP和无连接的UDP。 * 用户数据报协议UDP * 传输控制协议TCP > 运输协议数据单元TPDU:两个对等运输实体在通信时传送的数据单元。 运输层向高层用户屏蔽了下面网络核心的细节,他使应用进程看见的就是好像在两个运输层实体之间有一条端到端的逻辑通路,但这条逻辑通信信道对上层的表现却因运输层使用的不同协议而有很大的差别。当这种逻辑通信信道就相当于一条全双工的可靠信道。但当运输层采用无连接的UDP协议时,这种逻辑通信信道仍然是一条不可靠信道。  * 复用:应用层所有的应用进程都可以通过运输层再传送到IP层。 * 分用:运输层从IP层收到发送给各应用进程的数据后,必须分别交付执明的各应用进程。  ### 2.1 端口 1. 服务器端使用的端口号 这里分两类,最重要的一类叫熟知端口号或系统端口号。  值为0-1024 2. 客户端使用的端口号 值为49152-65535 这类端口号仅在客户进程运行时才动态选择。因此又叫短暂端口号。 ### 2.2 UDP #### 2.2.1 概述 1. UDP是无连接的 发送数据之前不需要建立连接,因此减少了开销和发送数据之前的时延。 2. 尽最大努力交付 及不保证可靠交付,因此主机不需要维持复杂的连接状态表。 3. 面向报文 发送方的UDP对应用程序交下来的报文,在添加首部后就向下交付IP层。UDP对应用层交下来的报文,既不合并,也不拆分。而是保留这些报文的边界。  4. UDP是没有控制拥塞的。 5. UDP支持一对一、一对多、多对一、多对多的交互通信。 6. 首部开销小,只有8字节,比TCP的20字节小。 #### 2.2.2 首部格式 1. 源端口 源端口号。在需要对方回信时选用。不需要的时候可用全0。 2. 目的端口 目的端口号。这在终点交付报文时必须使用。 3. 长度 UDP用户的数据报长度。其最小值时8(仅有首部)。 4. 检验和 检测UDP用户数据报在传输中是否有错。有错就丢弃。  注意:UDP用户数据报首部中检验和的计算方法有些特殊。在计算检验和时,要在UDP用户数据报之前增加12个字节的伪首部。和IP数据报的检验和只检验IP数据报的首部不同,UDP的检验和是把首部和数据部分一起都检验。  ### 2.3 TCP #### 2.3.1 特点 1. 面向连接的运输层协议。 在应用程序在使用TCP协议之前,必须先建立TCP连接。在传送数据完毕后,必须释放已经建立的TCP连接。 2. 每一条TCP连接只能有两个端点,每一条TCP连接只能是点对点的。 3. TCP提供可靠交付的服务。 通过TCP连接传送的数据,无差错,不丢失,不重复,并且按序到达。 4. TCP提供全双工通信。 TCP允许通信双方的应用进程在任何时候都能发送数据。 5. 面向字节流。 TCP的流是指流入到进程或从进程流出的字节序列。虽然应用程序和TCP的交互式一次一个数据块,但TCP把应用程序交下来的数据仅仅看成是一连串的无结构的字节流。  TCP报文段先要传送到IP层,加上IP层首部后,再传送到数据链路层。再加上数据链路层的首部和尾部后,才离开主机发送到物理链路。 ## 3. TCP 报文段首部 > TCP虽然是面向字节流的,但TCP传送的数据单元却是报文段。  * 源端口和目的端口:各占`2个字节`,分别写入源端口号和目的端口号。 * 序号:`占4字节`。序号范围是[0,2e32-1]个序号。序号增加到2e32-1后,下一个序号就又回到0。也就是说,序号使用mod 2^32运算。 > TCP是面向字节流的。在一个TCP连接中传送的字节流中的每一个字节都按顺序编号。整个要传送的字节流的起始序号必须在连接建立时设置。首部中的序号字段值则是指的是本报文段所发送的数据的第一个字节的序号。例如,一报文段的序号是301,而接待的数据共有100字节。这就表明:本报文段的数据的第一个字节的序号是301,最后一个字节的序号是400。显然,下一个报文段(如果还有的话)的数据序号应当从401开始,即下一个报文段的序号字段值应为401。这个字段的序号也叫“报文段序号”。 * 确认号:`占4字节`。是期望收到对方下一个报文段的第一个数据字节的序号。例如,B正确收到了A发送过来的一个报文段,其序号字段值是501,而数据长度是200字节(序号501~700),这表明B正确收到了A发送的到序号700为止的数据。因此,B期望收到A的下一个数据序号是701,于是B在发送给A的确认报文段中把确认号置是701。注意,现在确认号不是501,也不是700,而是701。 > 若确认号为= N,则表明:到序号N-1为止的所有数据都已正确收到。 * 数据偏移:`占4位`,它指出TCP报文段的数据起始处距离TCP报文段的起始处有多远。这个字段实际上是指出TCP报文段的首部长度。 > 由于首部中还有长度不确定的选项字段,因此数据偏移字段是必要的,但应注意,“数据偏移”的单位是32位字(即以4字节的字为计算单位)。由于4位二进制数能表示的最大十进制数字是15,因此数据偏移的最大值是60字节,这也是TCP首部的最大字节(即选项长度不能超过40字节)。 * 保留:`占6位`,保留为今后使用,但目前应置为0 。下面有6个控制位,用来说明本报文段的性质。 * 紧急`URG(URGent)`:当`URG=1`时,表明紧急指针字段有效。它告诉系统此报文段中有紧急数据,应尽快发送(相当于高优先级的数据),而不要按原来的排队顺序来传送。 > 例如,已经发送了很长的一个程序要在远地的主机上运行。但后来发现了一些问题,需要取消该程序的运行,因此用户从键盘发出中断命令。如果不使用紧急数据,那么这两个字符将存储在接收TCP的缓存末尾。只有在所有的数据被处理完毕后这两个字符才被交付接收方的应用进程。这样做就浪费了很多时间。 > 当URG置为1时,发送应用进程就告诉发送方的TCP有紧急数据要传送。于是发送方TCP就把紧急数据插入到本报文段数据的最前面,而在紧急数据后面的数据仍然是普通数据。这时要与首部中紧急指针(Urgent Pointer)字段配合使用。 * 确认ACK(ACKnowledgment):仅当`ACK = 1`时确认号字段才有效,当`ACK = 0`时确认号无效。TCP规定,在连接建立后所有的传送的报文段都必须把ACK置为1。 * 推送 PSH(PuSH): 当两个应用进程进行交互式的通信时,有时在一端的应用进程希望在键入一个命令后立即就能收到对方的响应。在这种情况下,`TCP`就可以使用推送(`push`)操作。这时,发送方`TCP`把`PSH`置为`1`,并立即创建一个报文段发送出去。接收方`TCP`收到`PSH=1`的报文段,就尽快地(即“推送”向前)交付接收应用进程。而不用再等到整个缓存都填满了后再向上交付。 * 复位RST(ReSeT):当`RST=1`时,表名`TCP`连接中出现了严重错误(如由于主机崩溃或其他原因),必须释放连接,然后再重新建立传输连接。`RST`置为1还用来拒绝一个非法的报文段或拒绝打开一个连接。 * 同步SYN(SYNchronization):在连接建立时用来同步序号。当`SYN=1`而`ACK=0`时,表明这是一个连接请求报文段。对方若同意建立连接,则应在响应的报文段中使`SYN=1`和`ACK=1`,因此`SYN`置为1就表示这是一个连接请求或连接接受报文。 * 终止FIN(FINis,意思是“完”“终”):用来释放一个连接。当`FIN=1`时,表明此报文段的发送发的数据已发送完毕,并要求释放运输连接。 * 窗口:占`2字节`。窗口值是`[ 0,2^16-1]`之间的整数。窗口指的是发送本报文段的一方的接受窗口(而不是自己的发送窗口)。窗口值告诉对方:从本报文段首部中的确认号算起,接收方目前允许对方发送的数据量(以字节为单位)。之所以要有这个限制,是因为接收方的数据缓存空间是有限的。总之,窗口值作为接收方让发送方设置其发送窗口的依据。 > 例如,发送了一个报文段,其确认号是701,窗口字段是1000.这就是告诉对方:“从701算起,我(即发送方报文段的一方)的接收缓存空间还可接受1000个字节数据(字节序号是701~1700),你在给我发数据时,必须考虑到这一点。” > 总之:窗口字段明确指出了现在允许对方发送的数据量。窗口值经常在动态变化。 * 检验和:占`2字节`。检验和字段检验的范围包括首部和数据这两部分。 > 和UDP用户数据报一样,在计算检验和时,要在`TCP`报文段的前面加上`12字节`的伪首部。 伪首部的格式和`UDP`用户数据报的伪首部一样。但应把伪首部第`4`个字段中的`17`改为`6`(TCP的协议号是`6`); 把第`5`字段中的`UDP`中的长度改为`TCP`长度。接收方收到此报文段后,仍要加上这个伪首部来计算检验和。若使用`TPv6`,则相应的伪首部也要改变。 * 紧急指针:占2字节。紧急指针仅在`URG=1`时才有意义,它指出本报文段中的紧急数据的字节数(紧急数据结束后就是普通数据) 。 > 因此,在紧急指针指出了紧急数据的末尾在报文段中的位置。当所有紧急数据都处理完时,TCP就告诉应用程序恢复到正常操作。值得注意的是,即使窗口为0时也可以发送紧急数据。 * 选项:长度可变,最长可达`4字节`。当没有使用“选项”时,`TCP`的首部长度是`20字节`。 > TCP最初只规定了一种选项,即最大报文段长度`MSS(Maximum Segment Szie)`。注意`MSS`这个名词含义。`MSS`是每一个`TCP`报文段中的数据字段的最大长度。数据字段加上`TCP`首部才等于整个的`TCP`报文段。所以`MSS`并不是整个`TCP`报文段的最大长度,而是`TCP报文段长度减去TCP首部长度`。 ## 4. TCP 连接建立,连接释放 ### 4.1 TCP 连接建立,三次握手 传输控制块TCB:存储了每一个连接中的一些重要信息。比如TCP连接表,指向发送和接收缓冲的指针,指向重传队列的指针,当前的发送和接收序列等等。 假设主机A是TCP客户程序,B是TCP服务器程序。最初两端的TCP进程都是处于CLOSED关闭状态,客户端A打开链接,服务器端被打开链接。一开始B的TCP服务器进程先创建传输控制块TCB,准备接受客户进程的链接请求,然后服务器进程就处于`LISTEN`收听状态,等待A的连接请求。 1. 然后A的进程首先创建传输控制模块TCB。向B发出连接请求报文段,这是首部当中的同步位`SYN=1`,同时选择一个初始序号`seq=x`。TCP规定,`SYN报文段`(即`SYN=1`的报文段)不能写数据,但要消耗掉一个序号。这时候A就进入了同步已发送的状态。 2. B收到连接请求报文段后,如果同意建立连接,则向A发送确认,在确认报文段中把`SYN`位和`AVK`位置都置为`1`,确认号为`ack+1`,同时也为自己选择一个初始序号y。同样的这个报文段也是不能写数据的,但同时要消耗掉一个序号。这时B进入了同步收到状态。 3. A收到B的确认之后,还要向B给出确认。确认报文段的`ACK`置1,确认号`ack=y+1`,而自己的`seq=x+1`。ACK报文段是可以携带数据的,但如果不携带数据则不消耗序号,在这种情况下,下一个数据报文段的序号仍为`seq=x+1`。 这时候TCP已经建立了。A进行入了已经建立连接的阶段状态。B收到确认后也进入了连接状态。 为什么A最后还要发送一次确认呢? 这主要为了防止已失效的连接请求报文段突然又传送到了B,因而产生错误。 已失效的连接请求报文段是什么? 1. 首先是正常情况,A发出连接请求,但因连接请求报文丢失而未收到确认。于是A再重传一次连接请求。后来收到了确认,建立了连接。数据传输完毕后,就释放了连接。A共发送了两次连接报文请求,其中第一个丢失,第二个到达了B,没有已失效的连接请求报文段。 2. 接下来是坏的情况,A发出的第一个连接请求报文段并没有丢失,而是在某些网络结点长时间滞留了,以致于到连接释放以后的某个时间才到达B。本来这是一个早已失效的报文段,但B收到此失效的连接请求报文段后,就误认为是A有发出一次新的连接请求。于是就向A发出确认报文段。同意报文连接。但是由于现在A并没有发出建立连接的请求,因此不会理睬B的确认,也不会向B发送数据。但B以为新的运输连接已经建立了,并一直等待A发送数据来,B的许多资源就这样白白浪费了! 采用三次握手的方法就可以防止上述现象的发生,例如刚才的异常情况,A不会向B发出确认。B由于收不到确认,就知道A并没有要求建立连接。这也是为什么要三次进行握手。 三次握手无敌了?? **你放屁!**。SYN- Flood攻击是当前网络上最为常见的DDoS攻击,也是最为经典的拒绝服务攻击。 攻击者首先伪造地址对 服务器发起SYN请求,服务器回应(SYN+ACK)包,而真实的IP会认为,我没有发送请求,不作回应。服务器没有收到回应,这样的话,服务器不知 道(SYN+ACK)是否发送成功,默认情况下会重试5次(tcp_syn_retries)。这样的话,对于服务器的内存,带宽都有很大的消耗。攻击者如果处于公网,可以伪造IP的话,对于服务器就很难根据IP来判断攻击者,给防护带来很大的困难。 那改进成四次握手就无敌啦?? **你放屁!**。三次握手有的缺陷,就算N此握手的确保,也一样会有相关的问题出现!三次握手是在连接顺利的基础上最大地合理利用网络资源。 ### 4.2 TCP 连接释放,四次挥手 数据传输完毕之后,通信的双方都可释放连接。现在A和B都处于`ESTABLISHED`状态。 1. A的应用进程先向TCP发出连接释放报文段,并停止再发送数据,主动关闭TCP连接。A把链接释放报文段首部的终止控制位`FIN`置为`1`,其序号为`seq=u`,它等于前面以传送过的数据的最后一个字节的序号加`1`.这时候A进入了`FIN-WAIT-1(终止等待1)`状态,等待B的确认。 > **注意**:TCP规定,FIN报文段即使不携带数据,他也消耗掉一个序号!! 2. B 收到链接释放报文段后即发出确认,确认号是`ack = u + 1`,而这个报文段自己的序号是`v`,等于B前面已传送过的数据的`最后一个字节的序号加1`.然后B就进入`CLOSE-WAIT(关闭等待)`状态。TCP服务器进程这时应通知高层应用进程,因而从A到B这个方向的链接就释放了,这时的TCP链接处于半关闭状态,即A已经没有数据要发送了,但B若发送数据,A仍要接收,也就是说,从B到A这个方向的连接并未关闭。这个状态可能要维持一段时间。 3. A收到来自B的确认后,就进入了`FIN-WAIT-2(终止等待2)`状态满等待B发出的连接释放报文段。若B已经没有要向A发送的数据,其应用进程就通知TCP释放连接,这时B发出的连接释放报文段必须使`FIN = 1`,现假定B的序号为`w`(在半关闭状态B可能又发送了一些数据)。B还必须重复上次已发送过的确认号`ack = u + 1`.这时B就进入`LAST-ACK(最后确认)`状态,等待A的确认。 4. A在收到了B的链接释放报文段后,必须对此发出确认。在确认报文段中把`ACK置1`,确认号`ack=w+1`,而自己的序号是`seq=u+1`(根据TCP标准,前面发送过的FIN报文段要消耗一个序号)。然后进入到`TIME-WAIT`(时间等待)状态。**注意:** 现在TCP连接`还没有还没有释放掉`。必须经过时间等待计时器设置的时间`2MSL`后,A才能进入CLOSED状态。 > 时间MSL叫做最长报文段寿命,RFC793建议设在两分钟。但是在现在工程来看两分钟太长了,所以TCP允许不同的实现可以根据具体情况使用更小的MSL值。 为啥要2MSL时间啊??? 原因如下 1. 为了保证A发送的最后一个ACK报文段能够到达B。这个ACK报文段有可能丢失,因而使处于在LAST-ASK状态的B收不到对己发送的FIN-ACK报文段的确认。B会超时重传这个FIN+ACK报文段,而A就能在2MSL时间内收到这个重传的FIN+ACK报文段。而A就能在2MSL时间内收到这个重传的FIN+ACK报文段。接着A重传一次确认,重新启动2MSL计时器。最后的A和B都正常进入CLOSED状态。如果A在TIME-WAIT状态不等待一段时间,而实发送完ACK报文段后立即释放连接,那么就无法收到B重传的FIN+ACK报文段,因而也不会再发送一次确认报文段。 2. 防止了“已失效的连接请求报文段”。A在发送完最后一个ACK报文段后,在经过时间2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失,这样就可以使下一个连接中不会出现这种旧的连接请求报文段。B只要收到了A发出的确认,就进入CLOSED状态。同样,B在撤销相应的传输控制块TCB后,就结束了这次的TCP连接。 所以B结束TCP连接的时间要比A早一些的。  ## 5. 可靠传输 CRC 检错、帧编号、确认和重传机制 ARQ, 连续 ARQ ### 5.1 工作原理 TCP发送的报文段使交给IP层传送的。但IP层只能提供尽最大努力服务。也就是说,TCP下面的网络所提供的是不可靠的传输。因此TCP必须采用适当的措施才能使得两个运输层之间的通信变得可靠。 > 理想的传输条件有下面两个特点 > > 1. 传输信道不产生差错 > 2. 不管发送方以多快的速度发送数据,接收方总是来得及处理收到的数据。 #### 5.1.1 停止等待协议 > 可靠传输中这个协议是最简单的,但是运输层并不是使用这个协议的。这里只是为了引出可靠传输的问题而已。 以下是假定数据传送只在一个方向进行。 * 无差错情况 A发送分组M1,发完就暂停发送,等待B的确认。收到M1就向A发送确认。A在收到了对M1的确认后,就再发送下一个分组M2。  * 出现差错 当B接收到M1时检测出了差错,就丢弃M1了,也不会通知A收到有差错的分组。也可能是M1在传输过程中丢失了,A也不会知道。所以在可靠传输中,只要A超过一定时间仍然没有收到确认,就认为刚才发送的分组丢失了,因而重传前面发送过的分组,这就叫**超时重传**。所以就会有一个超时计时器。如果超时计时器到期之前收到了对方的确认,就撤销该超时计时器。 **注意**以下几点: 1. A在发送完一个分组后,必须暂时保留已发送的分组的副本。只有在收到相应的确认后才能清楚暂时保留的分组副本。 2. 分组和确认分组都必须进行编号。这样才能明确是哪一个发送出去的分组收到了确认,而哪一个分组还没有收到确认收到。 3. 超时计时器的设置的重传时间应当比数据在分组传输的平均往返时间更长一些。但是不能过长,过长会导致传输效率低下,过短会导致不必要的重传。对于运输层的重传时间非常复杂,因为已经发出的分组还不知道经过哪些网络,以及这些网络将会产生多大的时延,这些都是不确定因素。  * 确认丢失和确认迟到 1. 左图a B所发送的对M1的确认丢失了。A在设定的超时重传时间内没有收到确认,并无法知道是自己发送的分组出错,丢失,或者是B发送的确认丢失了。因此A在超时计时器到期后就要重传M1。现在应注意B的动作,假定B又收到了重传的分组M1。这时应该采取两个行动。 - 丢弃这个重复的帧,不向上层交付。 - 向A发送确认。不能认为已经发送过确认就不再发送,因此A之所以重传M1就标识A没有收到对M1的确认。 2. 右图b 传输过程中没有出现差错,当B对分组M1的确认迟到了。A会收到重复的确认。对重复的确认的处理很简单:收到后就丢弃。B仍然会收到重复的M1,并且同样要丢弃重复的M1,并重复确认分组。 ``` 像上述的确认和重传机制,我们就可以在不可靠的传输网络上实现可靠的通信。 ```  > 所以像上述这种可靠传输协议常称为自动重传请求ARQ。 意思是重传的请求是自动进行的。接收方不需要请求发送方重传某个出错的分组。 * 信道利用率 TD:A发送分组需要的时间 RTT:往返时延 TA:发送确认分组需要时间TA  但是这个效率太低了! 所以有了流水线传输!  #### 5.1.2 连续ARQ协议 发送方维持发送窗口,位于发送窗口的5个分组都可连续发送出去,而不需要等待对方的确认。这样信道利用率就高了。而发送方每收到一个确认,就把发送窗口向前滑动一个分组的位置。 接收方一般都是蚕蛹累计确认的方式,也就是说,接收方不必对收到的分组逐个发送确认。而是收到几个分组后,对按需到达的最后一个分组发送确认, > 如果发送方发了前5个分组,而中间第3个分组丢失了。这时接收方只能对前两个分组发出确认。发送方无法知道后面三个分组的下落,而只好把后面的三个分组都再重传一次。这就叫Go-back-N(回退N),表示需要再退回去重传已发送过的N个分组。可见当通信线路信号不好的时候,连续ARQ协议会带来负面的影响。  ### 5.2 具体实现 #### 5.2.1 以字节为单位的滑动窗口 建议看这位博主的介绍,很详细了[以字节未单位的滑动窗口](https://blog.csdn.net/qq_40452317/article/details/90105456) 现假定A收到了B发来的确认报文段,其中窗口是20字节,而确认号是31(这表明B期望收到的下一个序号是31,而序号30为止的数据已经收到了)。根据这两个数据,A就构造出自己的发送窗口。  > 发送窗口表示:在没有收到B的确认的情况下,A可以连续把窗口内的数据都发送出去。在未收到确认之前都必须展示保留,以便在超时重传是使用。  从以上可知道 * A窗口: 小于P1的是已发送并已收到确认的部分,而大于P3的是不允许发送的部分。 P3-P1 = A的发送窗口 P2-P1 = 已发送但尚未收到确认的字节数 P3-P2 = 允许发送当前尚未发送的字节数(又称可用窗口或有效窗口数) * B窗口: B的接收窗口大小是20,在接收窗口外面,到30号为止的数据是已经发送过确认,并且已经交付主机了。因此在B可以不再保留这些数据。  A在据徐发送完序号42-53的数据后,指针P2向前移动和P3重合。发送窗口内的序号都已用完,但还没有在收到确认。由于A的发送窗口已满,可用窗口已经减少到0,因此必须停止发送。如果发送窗口内所有的数据都已正确到达B,B也早已发出了确认,但这些确认滞留在网络中,在没有收到确认时吗,A只能认为B还没有收到这些确认的数据。于是A经过由超时计算器控制时间后,就重传这部分数据。重新设置超时计时器,直到B的确认为止。  下面这是接受缓存和接受窗口的关系。  发送缓存用来暂时存放: 1. 发送应用程序传送给发送方TCP准备发送的数据。 2. TCP以发送出单尚未收到确认的数据。 发送窗口通常只是发送缓存的一部分。已被确认的数据应当从发送缓存中删除,因此发送缓存和发送窗口的后沿是重合的。发送应用程序最后写入发送缓存的字节减去最后被确认的字节,就是还保留在发送缓存中的被写入的字节数。发送应用程序必须控制写入缓存的速率,不能太快,否则发送缓存就没有存放数据的空间了。 接收缓存用来暂时存放: 1. 按序到达、但尚未被接收应用程序读取的数据。 2. 未按序到达的数据。 #### 5.2.2 超时重传时间的选择 参考博主 [超时重传时间的选择](https://blog.csdn.net/qq_40452317/article/details/90105513) TCP 超时重传时间设置,如果把超时重传时间设置得太短,就会引起很多报文段的不必要的重传,使网络负荷增大。但若把超时重传时间设置得过长,则又使网络的空闲时间增大,降低了传输效率。 TCP采用了一种自适应算法,它记录一个报文段发出的时间,以及收到相应的确认的时间。这两个时间之差就是**报文段的往返时间RTT**。 加权平均往返时间 TCP保留了RTT 的一个加权平均往返时间RTTS(这又称为 平滑的往返时间)。第一次测量到RTT 样本时,RTTS值就取为所测量到的RTT样本值。以后每测量到一个新的RTT 样本,就按下式重新计算一次RTTS:  超时重传时间RTO RTO (Retransmission Time-Out) 应略大于上面得出的加权平均往返时间RTTS。RFC 2988建议使用下式计算RTO。  RTTD是RTT的偏差的加权平均值。RFC 2988建议这样计算RTTD。第一次测量时,RTTD值取为测量到的RTT样本值的一半。在以后的测量中,则使用下式计算加权平均的RTTD:  是个小于1 的系数,其推荐值是1/4,即0.25。 TCP报文段1没有收到确认。重传(即报文段 2) 后,收到了确认报文段ACK。如何判定此确认报文段是对原来的报文段1的确认, 还是对重传的报文段2的确认? Karn 算法 在计算平均往返时间RTT时,只要报文段重传了, 就不采用其往返时间样本。 这样得出的加权平均平均往返时间 RTTS和超时重传时间RTO就较准确。 但是,这又引起新的问题。当报文段的时延突然增大了很多时,在原来得出的重传时间内,不会收到确认报文段。于是就重传报文段。 但根据 Karn算法,不考虑重传的报文段的往返时间样本。这样, 超时重传时间就无法更新。 报文段每重传一次,就把 RTO增大一些:  系数γ的典型值是2 。当不再发生报文段的重传时,才根据报文段的往返时延更新平均往返时延RTT和超时重传时间RTO的数值。 #### 5.2.3 选择确认SACK 参考博主 [选择确认SACK](https://blog.csdn.net/qq_35733751/article/details/80157509) TCP的接收方在接收方在接收对方发送过来的数据字节流的序号不连续,结果序号1001-1500没有收到。接下来的字节流又收到了,可是缺少了3001-3500。再后面从序号4501起又没有收到。也就是说,接收方收到了和前面的不连续的两个字节块。但要把这些信息准确高速发送方,使得发送方不要再发送这些已经收到的数据。  ## 6. TCP 窗口机制 一般来说,我们总是希望数据传的更快一些。但如果发送方把数据发送得过快,接收方就可能来不及接收,这就会造成数据得丢失。所谓流量控制就是让发送方的发送速率不要太快,要让接收方来的及接收。 下面是利用滑动窗口机制进行流量控制。  设A向B发送数据。在连接建立时,B告诉了A接收窗口rwnd = 400。因此发送方的发送窗口是不能超过接收方给出的接收窗口的数值。注意一点是TCP的窗口单位是字节,不是报文段。 假设报文段为100字节长,而数据报文段序号seq的初始值设为1,上面大写的ACK表示首部中的确认位ACK,小写ack表示确认字段的值。 我们应该注意到接收方主机B进行了三次流量控制。 1. 第一次把窗口减少到rwnd=300。 2. 第二次又减少到rwnd=100。 3. 最后是减小到0,即不允许发送方再发送数据了。 为了防止A一直等待B发送的非零窗口的情况(报文段在传输的时候丢失了!),而B也一直等到A发送的数据的问题,TCP为每一个连接都设置了一个持续计时器,只要TCP连接的以方收到了对方的零窗口通知。就启动持续计时器,若持续计时器设置的时间到期,就发送一个零窗口探测报文段,而对方就在确认这个探测报文段时给出了现在的窗口值。那么会有下面两种结果 1. 如果窗口仍是0的话,那么收到的这个报文段的一方就重新设置持续计时器。 2. 如果窗口不是0的话,那么就会打破等待。 ## 7. TCP 的超时重传时间计算 看例题! ## 8. TCP 的选择确认 SACK 看上面! 5.2.3 ## 9. TCP 的流量控制 (零窗口问题、糊涂窗口综合症) ### 9.1 零窗口问题 上面有! 第6点 ### 9.2 糊涂窗口综合症 假设TCP接收方的缓存已经满了,而交互式的应用进程一次只从接收缓存中读取1字节,然后向发送方发送确认,并把窗口设置为1个字节(但发送的数据报时40字节长),接着发送方又发来了1个字节的数据(请注意,发送方发送的IP数据报是41字节长)。接收方发回确认,仍然为1个字节。这样下去会使得网络的效率很低。 要解决这个问题,可以让接收方等待一段时间,使得或是接收混村以有足够空间容纳一个最长的报文段,或等待接收缓存已有一定空闲的空间。 ## 10. TCP 的拥塞控制 这里水很深,我把握不住(~太多内容了不想打了~ ) 看这位博主的吧[ TCP 的拥塞控制](https://blog.csdn.net/qq_41431406/article/details/97926927) ## 11. 课后习题 第一题(5-13) 一个 UDP 用户数据报的数据字段为 8192 字节。在链路层要使用以太网来传送。试问应当划分为几个 IP 数据报片?说明每一个 IP 数据报片的数据字段长度和片偏移字段的值。  第二题(5-14) 一个UDP用户数据报的首部的十六进制表示是06 32 00 45 00 1C E2 17。求源端口、目的端口、用户数据报总长度、数据部分长度。这个用户数据报是从客户发送给服务器的还是从服务器发送给客户的?使用UDP的这个服务器程序是什么?  第三题(5-21) 假设使用连续ARQ协议,发送窗口大小是3,而序列范围[0,15],而传输媒体保证在接收方能够按序收到分组。在某时刻,在接收方,下一个期望收到序号是5。 试问: ①在发送方的发送窗口中可能有出现的序号组合有哪几种? ②接收方已经发送出去的、但在网络中(即还未到达发送方)的确认分组可能有哪些?说明这些确认分组是用来确认哪些序号的分组。  第四题(5-23) 主机A向主机B连续发送了两个TCP报文段,其序号分别为70和100。试问: (1)第一个报文段携带了多少个字节的数据? (2)主机B收到第一个报文段后发回的确认中的确认号应当是多少? (3)如果主机B收到第二个报文段后发回的确认中的确认号是180,试问A发送的第二个报文段中的数据有多少字节? (4)如果A发送的第一个报文段丢失了,但第二个报文段到达了B。B在第二个报文段到达后向A发送确认。试问这个确认号应为多少?  第五题(5-27) 一个TCP报文段的数据部分最多为多少个字节?为什么?如果用户要传送的数据的字节长度超过TCP报文字段中的序号字段可能编出的最大序号,问还能否用TCP来传送?  第六题(5-31) 通信信道带宽为1Gbit/s,端到端时延为10ms,TCP的发送窗口为65535B,则可能达到的最大吞吐量是?信道利用率是多少?  第七题(5-34) 已知第一次测得TCP的往返时间RTT是30 ms。接着收到了三个确认报文段,用它们测量出的往返时间样本RTT分别是:26 ms,32 ms和24 ms。设α=0.1。试计算每一次的新的加权平均往返时间值RTT。讨论所得出的结果。  第八题(5-38) 设Tcp的ssthresh的初始值为8(单位为报文段),当拥塞窗口上升到12时网络发生了超时,Tcp使用慢开始和拥塞避免,试分别求出第1次到第15次传输的各拥塞窗口大小。 | 轮次 | 拥塞窗口 | 拥塞窗口变化的原因 | | - | - | - | | 1 | 1 | 网络发生了超时,TCP使用慢开始算法 | | 2 | 2 | 拥塞窗口值加倍 | | 3 | 4 | 拥塞窗口值加倍 | | 4 | 8 | 拥塞窗口值加倍,这是ssthresh的初始值 | | 5 | 9 | TCP使用拥塞避免算法,拥塞窗口值加1 | | 6 | 10 | TCP使用拥塞避免算法,拥塞窗口值加1 | | 7 | 11 | TCP使用拥塞避免算法,拥塞窗口值加1 | | 8 | 12 | TCP使用拥塞避免算法,拥塞窗口值加1 | | 9 | 1 | 网络发生了超时,TCP使用满开始算法 | | 10 | 2 | 拥塞窗口值加倍 | | 11 | 4 | 拥塞窗口值加倍 | | 12 | 6 | 拥塞窗口值加倍,但到达了12的一半时,改为了拥塞避免算法 | | 13 | 7 | TCP使用拥塞避免算法,拥塞窗口值加1 | | 14 | 8 | TCP使用拥塞避免算法,拥塞窗口值加1 | | 15 | 9 | TCP使用拥塞避免算法,拥塞窗口值加1 | 第九题(5-39) TCP 的拥塞窗口cwnd大小与传输轮次n的关系如下所示:  (1)试画出如图5-25所示的拥塞窗口与传输轮次的关系曲线。 (2)指明TCP工作在慢开始阶段的时间间隔。 (3)指明TCP工作在拥塞避免阶段的时间间隔。 (4)在第16轮次和第22轮次之后发送方是通过收到三个重复的确认还是通过超市检测到丢失了报文段? (5)在第1轮次,第18轮次和第24轮次发送时,门限ssthresh分别被设置为多大? (6)在第几轮次发送出第70个报文段? (7)假定在第26轮次之后收到了三个重复的确认,因而检测出了报文段的丢失,那么拥塞窗口cwnd和门限ssthresh应设置为多大? (1)  (2) > 慢开始时间间隔:[ 1 , 6 ] 和 [ 23, 26 ] (3) > 拥塞避免阶段的时间间隔:[ 6, 16 ] 和 [ 17, 22 ] (4)在第16轮次和第22轮次之后发送方是通过收到三个重复的确认还是通过超时检测到丢失了报文段? > 第16轮次之后发送方通过收到三个重复的确认,检测到丢失了报文段,下一个了轮次的拥塞窗口减半了。 在22轮次之后发送方是通过超时检测到丢失了报文段,下一个轮次的拥塞窗口下降到1了。 (5)在第1轮次,第18轮次和第24轮次发送时,门限ssthresh分别被设置为多大? > 在第1轮次发送时,门限ssthresh被设置为32,因为从第6轮次起就进入了拥塞避免状态,拥塞窗口每个轮次加1。 在第18轮次发送时,门限ssthresh被设置为发生拥塞时拥塞窗口42的一半,即21. 在第24轮次发送时,门限sshresh被设置为拥塞时拥塞窗口26的一半即13。 (6)在第几轮次发送出第70个报文段? > 在表上累加可知当第7轮的时候才>70。所以是第七轮。 (7)假定在第26轮次之后收到了三个重复的确认,因而检测出了报文段的丢失,那么拥塞窗口cwnd和门限ssthresh应设置为多大? > 检测出了报文段的丢失时拥塞窗口cwnd是8,因此拥塞窗口cwnd的数值应当减半等于4,而门限ssthresh应设置为检测出报文段丢失时拥塞窗口8的一半,就是4。 第十题(5-41) 用TCP传送512字节的数据,设窗口为100字节,而TCP报文段每次也是传送100字节的数据。再设发送端和接收端的起始序号分别选为100和200。试画出类似于书中图5-31的工作示意图,从连接建立... 用TCP传送512字节的数据,设窗口为100字节,而TCP报文段每次也是传送100字节的数据。再设发送端和接收端的起始序号分别选为100和200。试画出类似于书中图5-31的工作示意图,从连接建立阶段到连接释放都要画上。  第十一题(5-61) 在本题中列出的⑧种情况下,画出发送窗口的变化。并标明可用窗口的位置。已知主机A要向主机B发送3KB的数据。在TCP连接建立后,A的发送窗口大小是2KB。A的初始序号是0。 (1)一开始A发送1 KB的数据。 (2)接着A就一 直发送数据,直到把发送窗口用完。 (3)发送方A收到对第1000号字节的确认报文段。 (4) 发送方A再发送850 B的数据。 (5) 发送方A收到ack= 900的确认报文段。 (6) 发送方A收到对第2047号字节的确认报文段。 (7) 发送方A把剩下的数据全部都发送完。 (8) 发送方A收到ack= 3072的确认报文段。 1. 我们应当注意到,发送窗口 = 2KB 就是2*1024=2048个字节。因此发送窗口就是第0个到第2047字节为止,长度是2048字节。A开始就发送了1024个字节,因此发送窗口中左边的1024个字节已经用掉了(窗口的左边),而右边的蓝色部分的是可用的,从1024字节到2047字节为止。 2. 发送方A一直发送数据,直到把窗口发送用完。这时整个窗口都用掉了。可用窗口的大小是零了,一个字节也发不出去了。 3. 发送方A收到对第1000号字节的确认报文段,表明A收到确认好ack=1001的确认报。这时,发送串口的后沿向前移动,发送串口从第1001字节到第3048字节为止,可用窗口从第2048到3018为止。 4. 发送方A再发送850字节,使得可用窗口的后沿向前移动850字节,即移动到2898字节。现在的可用串口从第2898字节到第3048字节。 5. 发送方A收到ack=900的确认报文段,不会对其窗口状态有任何影响,这个是个迟到确定。 6. 发送方A收到对第2047号字节的确认报文段。A的发送窗口再向前移动。现在的发送窗口从第2014字节开始到第4095字节。可用窗口增大了,从第2898字节到4094字节。 7. 发送方A把剩下的数据全部都发送完,发送方A共有3KB的数据,编号从0到3071.因此现在的可用窗口变小了,因此新的发送窗口位置又向前移动,从3072号到第5119号。 8. 发送方A收到ack=3072的确认报文段,表明序号在3071和这以前的报文段都受到了,后面期望收到的报文段序号从3072开始。因此,新的发送窗口的位置又向前移动,从3072号到5119号。整个发送窗口也就是可用窗口。 --- ## 最后 转载自互联网!!!  最后修改:2021 年 11 月 13 日 © 来自互联网 打赏 赞赏作者 支付宝微信 赞 如果觉得我的文章对你有用,请随意赞赏
1 条评论
?语言类评语?