TCP 可靠传输机制详解 您所在的位置:网站首页 tcp发送报文段 TCP 可靠传输机制详解

TCP 可靠传输机制详解

2024-03-24 20:10| 来源: 网络整理| 查看: 265

目录

1 UDP&TCP的区别

2 TCP传输

2.1 TCP协议的特点

2.2 TCP 报文段

2.3 TCP "三次握手"

2.4 TCP "四次挥手"

3 TCP可靠传输

3.1 客户端和服务器端所经历的状态

3.2 TCP 协议如何保证可靠传输

3.3 校验

3.4 TCP流量控制

3.5 TCP拥塞控制

3.6 停止等待协议

4 面试相关问题

1 UDP&TCP的区别

UDP协议和TCP协议都是传输层协议。

     TCP(Transmission Control Protocol,传输控制协议)提供的是面向连接,可靠的字节流服务。即客户和服务器交换数据前,必须现在双方之间建立一个TCP连接,之后才能传输数据。并且提供超时重发,丢弃重复数据,检验数据,流量控制等功能,保证数据能从一端传到另一端。

    UDP(User Data Protocol,用户数据报协议)是一个简单的面向数据报的运输层协议。它不提供可靠性,只是把应用程序传给IP层的数据报发送出去,但是不能保证它们能到达目的地。由于UDP在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重发等机制,所以传输速度很快。

UDP应用场景: 1.面向数据报方式  2.网络数据大多为短消息   3.拥有大量Client  4.对数据安全性无特殊要求  5.网络负担非常重,但对响应速度要求高

不同点

报头不同

                           

    UDP首部,8个字节。UDP数据报最大长度64K(包含UDP首部),如果数据长度超过64K就需要在应用层手动分包,UDP无法保证包序,需要在应用层进行编号。

       

Tcp头,20字节。

源/目的端口号: 表示数据是从哪个进程来, 到哪个进程去; 32位序号/32位确认号: 不一定从0开始(作用:保证确认应答;保证数据按序到达;去重) 4位TCP报头长度: 表示该TCP头部有多少个32位bit(有多少个4字节); 所以TCP报头最大长度是(1111)15 * 4 = 60 字节 6位标志位:     1. URG: 紧急指针是否有效     2. ACK: 确认号是否有效     3. PSH: 提示接收端应用程序立刻从TCP缓冲区把数据读走     4. RST: 对方要求重新建立连接; 我们把携带RST标识的称为复位报文段     5. SYN: 请求建立连接; 我们把携带SYN标识的称为同步报文段     6. FIN: 通知对方, 本端要关闭了, 我们称携带FIN标识的为结束报文段 16位窗口大小: 接收缓冲区剩余的空间大小  16位校验和: 发送端填充, CRC校验. 接收端校验不通过, 则认为数据有问题. 此处的检验和不光包含TCP 首部, 也包含TCP数据部分.  16位紧急指针: 标识哪部分数据是紧急数据;   

TCP与UDP区别总结:

1、TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接 2、TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付。

Tcp通过校验和,重传控制,序号标识,滑动窗口、确认应答实现可靠传输。如丢包时的重发控制,还可以对次序乱掉的分包进行顺序控制。

3、UDP具有较好的实时性,工作效率比TCP高,适用于对高速传输和实时性有较高的通信或广播通信。

4、每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信

5、TCP对系统资源要求较多,UDP对系统资源要求较少。

1.基于连接与无连接;    2.对系统资源的要求(TCP较多,UDP少);    3.UDP程序结构较简单;4.字节流模式与数据报模式; 5.TCP保证数据正确性,UDP可能丢包,TCP保证数据顺序,UDP不保证。

为什么UDP有时比TCP更有优势?

UDP以其简单、传输快的优势,在越来越多场景下取代了TCP,如实时游戏。

(1)网速的提升给UDP的稳定性提供可靠网络保障,丢包率很低,如果使用应用层重传,能够确保传输的可靠性。

(2)TCP为了实现网络通信的可靠性,使用了复杂的拥塞控制算法,建立了繁琐的握手过程,由于TCP内置的系统协议栈中,极难对其进行改进。

采用TCP,一旦发生丢包,TCP会将后续的包缓存起来,等前面的包重传并接收到后再继续发送,延时会越来越大,基于UDP对实时性要求较为严格的情况下,采用自定义重传机制,能够把丢包产生的延迟降到最低,尽量减少网络问题对游戏性造成影响。

2 TCP传输

2.1 TCP协议的特点

TCP 是在不可靠的 IP 层之上实现的可靠的数据传输协议,它主要解决传输的可靠、有序、无丢失和不重复的问题。TCP 的主要特点有:

(1) TCP 是面向连接的传输层协议。

(2) 每一条 TCP 连接只能有两个端点,每一条 TCP 连接只能是点对点的(一对一)。

(3) TCP 提供可靠的交付服务,保证传送的数据无差错、不丢失、不重复且有序。

(4) TCP 提供全双工通信,TCP 允许通信双方的应用进程在任何时候都能发送数据,为此 TCP 连接的两端都设有发送缓存和接收缓存,用来临时存放双向通信的数据。

发送缓存用来暂存以下数据:①应用程序传送给发送方 TCP 准备发送的数据;② TCP 已发送出但尚未收到的确认的数据。

接收缓存用来暂存以下数据:①按序到达的但尚未被接收应用程序读取的数据;②不按序到达的数据。

(5) TCP 是面向字节流的,虽然应用程序和 TCP 的交互是一次一个数据块,但 TCP 把应用程序交下来的数据看成仅仅是一连串的无结构的字节流。

2.2 TCP 报文段

TCP 传输的数据单元称为报文段。一个 TCP 报文段分为 TCP 首部和 TCP 数据两部分,整个 TCP 段作为 IP 数据报的数据部分封装在 IP 数据报中。

各字段的含义如下:

(1) 源端口和目的端口:各占2个字节。端口是运输层与应用层的服务接口。运输层的复用和分用功能都要通过端口才能实现。

(2) 序号:占4个字节。TCP是面向字节流的,所以TCP连接中传送的数据流中的每一个字节都编上一个序号。序号字段的值则指的是本报文段所发送的数据的第一个字节的序号。例如,一个报文段的序号字段值是200,携带的数据总共有100字节,表明这个报文段的数据的最后一个字节的序号是299,所以下一个报文段的数据序号应从300开始。

(3) 确认号:占4个字节,是期望收到对方的下一个报文段的数据的第一个字节的序号。若确认号为N,表明前N-1的所有数据都已经正确接收。例如,B正确的收到了A发送过来的一个报文段,其序号字段是指501,而数据长度是200字节(序号501~700),表明B正确的收到了A发送的序号700之前的数据。因此B希望收到A的下一个数据序号是701,所以B在发送给A的确认报文段中应把确认号设置成701。

(4) 数据偏移量:占4位,这里不是IP数据报分片的那个数据偏移,而是表示首部长度,它指出TCP报文段的数据起始处距离TCP报文段的起始处有多远。该字段若为15,则表明TCP首部达到最大长度60字节(以4字节为计算单位乘以15)。

(5) 保留:占6位,目前不使用,所以置为0。

(6) 紧急位 URG:当其值为1时,表明紧急指针字段有效。它会告诉系统此报文段中有紧急数据,应该尽快传送。但是URG需要和紧急指针配套使用,即从第一个字节到紧急指针所指字节就是紧急数据。

(7) 确认位 ACK:只有当ACK=1时,确认号字段才有效。TCP规定,在连接建立后所有传送的报文段都必须把ACK置为1。

(8) 推送位 PSH:TCP收到PSH=1的报文段,就尽快的交付接收应用进程,而不再等到整个缓存都填满了后再向上交付。

(9) 复位位 RST:当RST=1时,表明TCP连接中出现了严重的错误,必须释放连接,然后再重新建立运输连接。

(10) 同步位 SYN:SYN=1表示这是一个连接请求或连接接收报文。当SYN=1,ACK=0时,表明这是一个连接请求报文,对方若同意建立连接,则在响应报文中使用SYN=1,ACK=1。

(11) 终止位 FIN:用来释放一个连接。FIN=1表明此报文段的发送方的数据已经发送完毕,并要求释放传输连接。

(12) 窗口:占2个字节。它指出现在允许对方发送的数据量,接收方的数据缓存空间是有限的,所以使用窗口值作为接收方让发送方设置其发送窗口的依据,单位是字节。例如,设确认号是101,窗口字段是1000。这就表明,从101号开始,发送此报文段的一方还有接收1000字节数据(字节序号是101~1100)的接收缓存空间。

(13) 校验和:占2个字节。它的检验范围包括首部和数据部分。计算时要在TCP报文段前面加上12字节的伪首部。

(14) 紧急指针:占16位,指出在本报文段中紧急数据共有多少个字节。

(15) 选项:长度可变。TCP最初只规定了一种选项,即最大报文段长度(MSS)。

(16) 填充:这是为了使整个首部长度是4字节的整数倍。

主要需要理解以下几个字段:

源端口号和目标端口号:谁发的和发给谁(类似于哲学问题:你是谁?从哪里来?到哪里去?);

序号:为了解决乱序问题;

确认序号:发出去的包应该有确认,没有收到就应该重新发送,直到送达;

状态位:常见的有SYN、ACK、FIN,分别表示发起一个连接、确认和结束连接;

窗口大小:用于TCP流量控制,通信双方各声明一个窗口,说明自己当前的处理能力。发送的太快,处理不了,发的太慢,影响发送的效率;

2.3 TCP "三次握手"

第一次握手:客户端首先向服务器发送一个连接请求报文段。这个特殊的报文段中不含应用层数据,其首部中的SYN标志位被置为1。另外,客户端会随机选择一个起始号seq=x(连接请求报文不携带数据,但要消耗掉一个序号)。客户端进程进入SYN_SENT(同步发送)状态。 

第二次握手:服务器收到连接请求报文段后,如同意建立连接,就向客户端发回确认,并为该TCP连接分配TCP缓存和变量。在确认报文段中,SYN和ACK位都被置为1,确认号字段的值为x+1,并且服务器随机产生起始序号seq=y(确认报文不携带数据,但也要消耗掉一个序号)。确认报文段同样不包含应用层数据。服务端进入SYN_RCVD(同步接收)状态。

第三次握手:当客户端收到确认报文段后,还要向服务器给出确认,并且也要给该连接分配缓存和变量。这个报文段的ACK标志位被置为1,序号字段为x+1,确认号字段为ack=y+1。该报文可以携带数据,如果不携带数据则不消耗序号。客户端进入ESTABLISHED(建立连接)状态。

在成功的完成以上三步后,TCP连接就建立了,接下来就可以传送应用层数据了。TCP提供的是全双工通信,因此通信双方的应用进程在任何时候都能发送数据。注意:服务器端的资源是在完成第二次握手时分配的,而客户端的资源是在完成第三次握手时分配的。所以服务器易于受到SYN洪泛攻击。

TCP "三次握手"报文详细分析

TCP报文:[29 05 01 bb f4 0a 2c 77 1f a9 79 d2 50 10 01 00 b9 84 00 00] 为了更易理解:[29 05 01 bb] [f4 0a 2c 77] [1f a9 79 d2] [50 10 01 00] [b9 84 00 00] 源端口:2905(HEX) = 10501(DEC) 目的端口:01bb(HEX) = 443(DEC) 序号:1 为什么连接过程中的"序号"显示1,而相应字段的值不是1。详情请看面试问题的(6) 确认号:1 十六进制[50 10]转化成二进制[0101 0000 0001 0000] 数据偏移(占4位):单位是4个字节,此字段值为5,所以TCP首部的长度是20字节。 保留(占6位):保留为今后使用,目前置为0。 紧急位URG:0 确认位ACK:1 推送位PSH:0 复位位RST:0 同步位SYN:0 终止位FIN:0 窗口:0100(HEX) = 256(DEC) 检验和:0xb984 紧急指针:0 2.4 TCP "四次挥手"

参与TCP连接的两个进程中的任何一个都能终止该连接。

第一步:若客户端打算关闭连接,就向其服务器发送一个连接释放报文段,并停止再发送数据,主动关闭TCP连接,该报文段的FIN标志位被置为1,seq=u,它等于前面已传送过的数据的最后一个字节的序号加1(FIN报文段即使不携带数据,也要消耗掉一个序号)。TCP是全双工的,即可以想象成是一条TCP连接上有两条数据通路。当发送FIN报文时,发送FIN的一端就不能再发送数据,也就是关闭了其中一条数据通路,但另一条没有关闭的数据通路仍可以发送数据。

第二步:服务器收到连接释放报文段后就会发出确认,确认号为ack=u+1,而这个报文段自己的序号是v,等于它前面已传送过的数据的最后一个字节的序号加1。此时,从客户端到服务器这个方向的连接就释放了,TCP连接处于半关闭状态。但服务器若发送数据,客户端仍能接收,即从服务器到客户端这个方向的连接并未关闭。

第三步:若服务器已经没有要向客户端发送的数据,就释放连接,此时发出FIN=1的连接释放报文段。

第四步:客户端收到连接释放报文段后,必须发出确认。在确认报文段中,ACK字段被置为1,确认号ack=w+1,序号seq=u+1。此时TCP连接还没有释放掉,必须经过2MSL后,客户端才进入连接关闭状态。

3 TCP可靠传输 3.1 客户端和服务器端所经历的状态

结合连接和释放过程图看状态转换图,以下是客户端的状态转换图:

服务器端的状态转换图:

完整的状态转换图(红线是客户端的过程,蓝线是服务器的过程,表示正常的连接和断开过程):

断开过程中的状态解析

(1) FIN_WAIT_1:  FIN_WAIT_1 和 FIN_WAIT_2 状态的真正含义都是表示等待对方的 FIN 报文。而这两种状态的区别是:  FIN_WAIT_1 状态实际上是当 socket 在ESTABLISHED状态时,它想主动关闭连接,向对方发送了 FIN 报文,此时该 socket  即进入到 FIN_WAIT_1 状态。而当对方回应 ACK 报文后,则进入到 FIN_WAIT_2 状态。当然在实际的正常情况下, FIN_WAIT_1 状态一般是比较难见到的(这个过程比较快),而 FIN_WAIT_2 状态还有时常常可以用 netstat 看到(因为有一方还在发数据)。(主动关闭连接)

(2) FIN_WAIT_2:上面已经详细解释了这种状态,实际上 FIN_WAIT_2 状态下的 socket 表示半连接,即有一方要求 close 连接,但另外一方告诉对方,我暂时还有点数据需要传送给你(发送 ACK 报文),稍后再关闭连接。(主动关闭连接)

(3) TIME_WAIT:表示收到了对方的 FIN 报文,并发送出了 ACK 报文,就等 2MSL 后即可回到 CLOSED 可用状态了。如果 FIN_WAIT_1 状态下,收到了对方同时带 FIN 标志和 ACK 标志的报文时(被动方没有数据发送),可以直接进入到 TIME_WAIT 状态,而无须经过 FIN_WAIT_2 状态。(主动关闭连接)

(4) CLOSING(比较少见): 这种状态比较特殊,实际情况中应该是很少见,属于一种比较罕见的例外状态。正常情况下,当你发送 FIN 报文后,按理来说是应该先收到(或同时收到)对方的 ACK 报文,再收到对方的 FIN 报文。但是 CLOSING 状态表示你发送 FIN 报文后,并没有收到对方的 ACK 报文,反而却也收到了对方的 FIN 报文。什么情况下会出现此种情况呢?其实细想一下,也不难得出结论:那就是如果双方几乎在同时关闭一个 socket 的话,那么就出现了双方同时发送 FIN 报文的情况,也即会出现 CLOSING 状态,表示双方都正在关闭 socket 连接。

(5) CLOSE_WAIT: 被动方需要查看是否还有数据发送给对方,如果没有的话,那么你也就可以关闭这个 socket,发送 FIN 报文给对方,即关闭连接。所以在 CLOSE_WAIT 状态下,需要完成的事情是等待被动方去关闭连接。(被动方)

(6) LAST_ACK: 它是被动关闭的一方在发送 FIN 报文后,最后等待对方的 ACK 报文。当收到 ACK 报文后,也即可以进入到 CLOSED 可用状态了。(被动方)

(7) CLOSED: 表示连接中断。

小总结:

半关闭状态的含义是:通信的一端可以发送 FIN 报文段给对方,告诉它本端已经完成了数据的发送,但允许继续接收来自对方的数据,直到对方也发送 FIN 报文段以关闭连接。

当客户端处于 FIN_WAIT_2 状态时,服务器处于 CLOSE_WAIT 状态,这时可能会处于半连接状态,即服务器还有数据发给客户端。如果服务器没有数据发送,则发送 FIN 报文段关闭连接,而客户端将确认并进入 TIME_WAIT 状态。

上面的状态转换图还给出了 FIN_WAIT_1 状态直接进入 TIME_WAIT 状态的一条线路,前提是处于 FIN_WAIT_1 的客户端直接收到了带有确认信息的 FIN 报文段(而不是正常情况下的先收到 ACK 报文段,再收到 FIN 报文段)。

断开连接时的意外

当 TCP 连接发生一些物理上的意外情况时,例如网线断开,linux 上的 TCP 实现会依然认为该连接有效,而 windows 则会在一定时间后返回错误信息。这似乎可以通过设置 SO_KEEPALIVE 选项来解决,不过不知道这个选项是否对于所有平台都有效。

TIME_WAIT 状态所带来的影响

当某个连接的一端处于 TIME_WAIT 状态时,该连接将不能再被使用。事实上,对于我们比较有现实意义的是,这个端口将不能再被使用。某个端口处于 TIME_WAIT 状态(其实应该是这个连接)时,这意味着这个 TCP 连接并没有断开(完全断开),那么,如果你 bind 这个端口,就会失败。对于服务器而言,如果服务器突然 crash 掉了,那么它将无法再 2MSL 内重新启动,因为 bind 会失败。解决这个问题的一个方法就是设置 socket 的 SO_REUSEADDR 选项。这个选项意味着你可以重用一个地址。

注意:当建立一个 TCP 连接时,服务器端会继续用原有端口监听,同时用这个端口与客户端通信。而客户端默认情况下会使用一个随机端口与服务器端的监听端口通信。有时候,为了服务器端的安全性,我们需要对客户端进行验证,即限定某个 IP 某个特定端口的客户端。客户端可以使用 bind 来使用特定的端口。对于服务器端,当设置了 SO_REUSEADDR 选项时,它可以在 2MSL 内启动并 listen 成功。 但是对于客户端,当使用 bind 并设置 SO_REUSEADDR 时,如果在 2MSL 内启动,虽然 bind 会成功,但是在 windows 平台上 connect 会失败。而在 linux 上则不存在这个问题。

3.2 TCP 协议如何保证可靠传输

TCP的任务是在IP层的不可靠、尽力而为服务的基础上建立一种可靠数据传输服务。TCP提供的可靠数据传输服务就是要保证接收方进程从缓冲区读出的字节流与发送方发出的字节流是完全一样的。TCP使用了校验、序号、确认和重传机制来达到这个目的。

TCP,控制传输协议,和UDP的差别很大,它充分实现了数据传输时的各种控制功能:针对发送端发出的数据包的确认应答信号ACK针对数据包丢失或者出现定时器超时的重发机制针对数据包到达接收端主机顺序乱掉的顺序控制针对高效传输数据包的流动窗口控制针对避免网络拥堵时候的流量控制针对刚开始启动的时候避免一下子发送大量数据包而导致网络瘫痪的慢启动算法和拥塞控制。 而这些在UDP中都是没有的!此外,TCP作为一种面向有连接的控制传输协议,只有在确认对端主机存在时才会发送数据,从而可以控制通信流量的浪费。

TCP通过序列号、检验和、确认应答信号、重发控制、连接管理、窗口控制、流量控制、拥塞控制实现可靠性。

应用数据被分割成 TCP 认为最适合发送的数据块。TCP 给发送的每一个包进行编号,接收方对数据包进行排序,把有序数据传送给应用层。校验和: TCP 将保持它首部和数据的检验和。这是一个端到端的检验和,目的是检测数据在传输过程中的任何变化。如果收到段的检验和有差错,TCP 将丢弃这个报文段和不确认收到此报文段。TCP 的接收端会丢弃重复的数据。流量控制: TCP 连接的每一方都有固定大小的缓冲空间,TCP的接收端只允许发送端发送接收端缓冲区能接纳的数据。当接收方来不及处理发送方的数据,能提示发送方降低发送的速率,防止包丢失。TCP 使用的流量控制协议是可变大小的滑动窗口协议。 (TCP 利用滑动窗口实现流量控制)拥塞控制: 当网络拥塞时,减少数据的发送。停止等待协议: 也是为了实现可靠传输的,它的基本原理就是每发完一个分组就- 停止发送,等待对方确认。在收到确认后再发下一个分组。 超时重传: 当 TCP 发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段。 3.3 校验

校验

在计算校验和时,要在TCP数据报之前增加12个字节的伪首部,伪首部并不是TCP报文段真正的首部。只是在计算校验和时,临时添加在TCP数据报文段的前面,得到一个临时的TCP报文段。伪首部既不向下传送也不向上递交,而仅仅是为了计算校验和。注意:IP数据报的校验和只检验IP数据报的首部,但TCP的校验和会把首部和数据部分一起检验。

序号

TCP首部的序号字段用来保证数据能有序提交给应用层,TCP把数据看成一个无结构但是有序的字节流,而序号是建立在传送的字节流之上,而不是建立在报文段之上。TCP连接中传送的数据流中的每一个字节都编上一个序号。序号字段的值则指的是本报文段所发送的数据的第一个字节的序号。

确认

TCP首部的确认号是期望收到对方的下一个报文段的数据的第一个字节的序号。TCP默认使用累计确认,即TCP只确认数据流中至第一个丢失字节为止的字节。例如,接收方B收到了发送方A发送的包含字节0~2和6~7的报文段。由于某些原因,B还没有收到字节3~5的报文段,此时B仍在等待字节3(和其后面的字节),因此,B到A的下一个报文段将确认号字段设置为3。

重传

有两种事件会导致TCP对报文段进行重传:超时和冗余ACK。

(1) 超时

TCP每发送一个报文段,就对这个报文段设置一次计时器。只要计时器设置的重传时间到期但还没有收到确认,就要重传这一报文段。当检测到接收数据有错误时,会采取直接丢弃出错的数据,发送端等待接收端的确认超时后,会自动重发该报文段。

由于IP数据报在传输的时候选择的路由变化很大,因此传输层的往返时延的方差很大。为了计算超时计时器的重传时间,TCP采用一种自适应算法,它记录一个报文段发出的时间,以及收到相应确认的时间,这两个时间之差叫做报文段的往返时间(RTT)。TCP保留了RTT的一个加权平均往返时间RTTs,当第一次测量RTT样本时,RTTs值就为所测量到的RTT样本的值,但之后每测量一个新的RTT样本,就按下式重新计算一次RTTs:

新的RTTs = ( 1- a ) * (旧的RTTs) + a(新的RTT样本)

在上式中0 ssthresh,则下一个RTT的cwnd应等于ssthresh,而不是2*cwnd,即cwnd不能越过ssthresh值。如上图,在16个轮次时,cwnd=8、ssthresh=12,第17轮次时,cwnd=12,而不是16。

快重传和快恢复

(1)快重传

TCP可靠传输机制中,快速重传技术使用了冗余ACK来检测丢包的发生。同样,冗余ACK也用于网络拥塞的检测。快重传并非取消重传计时器,而是在某些情况下可更早的重传丢失的报文段。当发送方连续收到三个重复的ACK报文时,直接重传对方尚未收到的报文段,而不必等待那个报文段设置的重传计时器超时。

如果收到3个相同的ACK。TCP在收到乱序到达包时就会立即发送ACK,TCP利用3个相同的ACK来判定数据包的丢失,此时进行快速重传,快速重传做的事情有:

1.把ssthresh设置为cwnd的一半。

2.把cwnd再设置为ssthresh的值(具体实现有些为ssthresh+3)。

3.重新进入拥塞避免阶段。

(2)快恢复

后来的"快速恢复"算法是在上述的"快速重传"算法后添加的,当收到3个重复ACK时,TCP最后进入的不是拥塞避免阶段,而是快速恢复阶段。快速重传和快速恢复算法一般同时使用。快速恢复的思想是"数据包守恒"原则,即同一个时刻在网络中的数据包数量是恒定的,只有当"老"数据包离开了网络后,才能向网络中发送一个"新"的数据包,如果发送方收到一个重复的ACK,那么根据TCP的ACK机制就表明有一个数据包离开了网络,于是cwnd加1。如果能够严格按照该原则那么网络中很少会发生拥塞,事实上拥塞控制的目的也就在修正违反该原则的地方。

具体来说快速恢复的主要步骤是:

1.当收到3个重复ACK时,把ssthresh设置为cwnd的一半,把cwnd设置为ssthresh的值加3(有的实现版本不加3),然后重传丢失的报文段,加3的原因是因为收到3个重复的ACK,表明有3个"老"的数据包离开了网络。

2.再收到重复的ACK时,拥塞窗口增加1。

3.当收到新的数据包的ACK时,把cwnd设置为第一步中的ssthresh的值。原因是因为该ACK确认了新的数据,说明从重复ACK时的数据都已收到,该恢复过程已经结束,可以回到恢复之前的状态了,也即再次进入拥塞避免状态。

快速重传算法首次出现在4.3BSD的Tahoe版本,快速恢复首次出现在4.3BSD的Reno版本,也称之为Reno版的TCP拥塞控制算法。

在流量控制中,发送方发送数据的量由接收方决定,而在拥塞控制中,有发送方自己通过检测网络状况而决定。实际上,慢开始、拥塞避免算法、快重传和快恢复集中算法应该是同时应用在拥塞控制机制之中的,当发送方检测到超时的时候就采用慢开始和拥塞避免,当发送方接收到冗余ACK的时候就采用快重传和快恢复。

3.6 停止等待协议

停止等待协议是为了实现可靠传输的,它的基本原理就是每发完一个分组就停止发送,等待对方确认。在收到确认后再发下一个分组; 在停止等待协议中,若接收方收到重复分组,就丢弃该分组,但同时还要发送确认;

无差错情况:

发送方发送分组,接收方在规定时间内收到,并且回复确认.发送方再次发送。

出现差错情况(超时重传):

停止等待协议中超时重传是指只要超过一段时间仍然没有收到确认,就重传前面发送过的分组(认为刚才发送过的分组丢失了)。因此每发送完一个分组需要设置一个超时计时器,其重转时间应比数据在分组传输的平均往返时间更长一些。这种自动重传方式常称为 自动重传请求 ARQ 。另外在停止等待协议中若收到重复分组,就丢弃该分组,但同时还要发送确认。连续 ARQ 协议 可提高信道利用率。发送维持一个发送窗口,凡位于发送窗口内的分组可连续发送出去,而不需要等待对方确认。接收方一般采用累积确认,对按序到达的最后一个分组发送确认,表明到这个分组位置的所有分组都已经正确收到了。

确认丢失和确认迟到

确认丢失:确认消息在传输过程丢失

当A发送M1消息,B收到后,B向A发送了一个M1确认消息,但却在传输过程中丢失。而A并不知道,在超时计时过后,A重传M1消息,B再次收到该消息后采取以下两点措施:

丢弃这个重复的M1消息,不向上层交付。 向A发送确认消息。(不会认为已经发送过了,就不再发送。A能重传,就证明B的确认消息丢失)。 确认迟到 :确认消息在传输过程中迟到

 

 

A发送M1消息,B收到并发送确认。在超时时间内没有收到确认消息,A重传M1消息,B仍然收到并继续发送确认消息(B收到了2份M1)。此时A收到了B第二次发送的确认消息。接着发送其他数据。过了一会,A收到了B第一次发送的对M1的确认消息(A也收到了2份确认消息)。处理如下:

A收到重复的确认后,直接丢弃。B收到重复的M1后,也直接丢弃重复的M1。

自动重传请求 ARQ 协议

停止等待协议中超时重传是指只要超过一段时间仍然没有收到确认,就重传前面发送过的分组(认为刚才发送过的分组丢失了)。因此每发送完一个分组需要设置一个超时计时器,其重转时间应比数据在分组传输的平均往返时间更长一些。这种自动重传方式常称为自动重传请求ARQ。

优点: 简单缺点: 信道利用率低

连续ARQ协议

连续 ARQ 协议可提高信道利用率。发送方维持一个发送窗口,凡位于发送窗口内的分组可以连续发送出去,而不需要等待对方确认。接收方一般采用累计确认,对按序到达的最后一个分组发送确认,表明到这个分组为止的所有分组都已经正确收到了。

优点: 信道利用率高,容易实现,即使确认丢失,也不必重传。缺点: 不能向发送方反映出接收方已经正确收到的所有分组的信息。 比如:发送方发送了 5条 消息,中间第三条丢失(3号),这时接收方只能对前两个发送确认。发送方无法知道后三个分组的下落,而只好把后三个全部重传一次。这也叫 Go-Back-N(回退 N),表示需要退回来重传已经发送过的 N 个消息。 4 面试相关问题

(1)为什么四次挥手发送最后一次报文后要等待2MSL (报文最大生存时间)的时间?

答:(1)为了保证A发送的最后一个确认报文段能够到达B。如果A不等待2MSL,若A返回的最后确认报文段丢失,则B不能进入正常关闭状态,而A此时已经关闭,也不可能再重传。

(2)防止出现”已失效的连接请求报文段”。A在发送完最后一个确认报文段后,再经过2MSL可保证本连接持续的时间内所产生的所有报文段从网络中消失。

(2)TCP使用的是GBN(后退N帧协议)还是SR(选择重传协议)?

答:这是为了让人踩坑而出的问题。因为TCP使用累计确认,看起来像是GBN。但是,正确收到但失序的报文并不会被丢弃,而是缓存起来,并且发送冗余ACK指明希望收到的下一个报文段,这是TCP方式和GBN的显著区别。例如,A发送了N个报文段,其中第k(k < N)个报文段丢失,其余N-1个报文段正确地按序到达接收方B。当使用GBN时,A需要重传分组k,以及所有后继分组k+1,k+2,...,N。相反,TCP却最多重传一个报文段,即报文段k。另外,TCP中提供一个SACK(Selective ACK)选项,也就是选择确认选项。当使用选择确认选项的时候,TCP看起来就和SR非常相似。因此,TCP的差错恢复机制可以看成是GBN和SR协议的混合体。

(3)为什么超时时间发生时cwnd被置为1,而收到3个冗余ACK时cwnd只是减半?

答:首先应分析那种情况的网络拥塞程度更严重。其实不难发现,在收到3个冗余ACK的情况下,网络虽然拥塞,但至少ACK报文段能够被正确交付。而当超时发生时,说明网络可能已经拥塞的连ACK报文段都传输不了了,发送方只能等待超时后重传数据。因此,超时时间发生时,网络拥塞更严重,所以发送方应该最大限度地抑制数据发送量,所以cwnd置为1;收到3个冗余ACK时,网络拥塞相对而言不是很严重,所以cwnd减半即可。

(4)为什么不采用"两次握手"建立连接?

答:这主要是为了防止两次握手情况下已失效的连接请求报文段突然有传送到服务端,而产生了错误。考虑以下情况:客户A想服务器B发送TCP连接请求,第一个连接请求报文在网络的某个结点长时间滞留,A超时后认为报文丢失,于是再重传一次连接请求,B收到后建立连接。数据传输完毕后双方断开连接。此时,前一个滞留在网络中的连接请求到达了服务端B,而B认为A有发来连接请求,此时若是使用"三次握手",则B向A返回确认报文段,由于是一个失效的请求,因此A不予理睬,建立连接失败。若采用的是"两次握手",则这种情况下B认为传输连接已经建立,并一直等待A传输数据,而A此时并无连接请求,因此不予理睬,这样就造成了B的资源白白浪费了。

(5)是否TCP和UDP都需要计算往返时间RTT?

答:往返时间RTT只是针对传输层TCP协议才很重要,因为TCP要根据RTT的值来设置超时计时器的超时时间。UDP没有确认和重传机制,因此RTT对UDP没有什么意义。

(6)为什么TCP在建立连接的时候不能每次选择相同的、固定的初始序号?

答:(1)假如A和B频繁地建立连接,传送一些TCP报文段后再释放连接,然后又不断的建立新的连接、传送报文段和释放连接。

(2)假如每一次建立连接时,主机A都选择相同的、固定的初始序号,如1。

(3)若主机A发送出的某些TCP报文段在网络中会滞留较长的时间,以致造成主机A超时重传这些TCP报文段。

(4)若有一些在网络中滞留时间较长的TCP报文段最后终于到达了主机B,但这时传送该报文段的那个连接早已释放了,而在到达主机B时的TCP连接是一条新的TCP连接。

以上这些情况可能会导致在新的TCP连接中的主机B有可能会接收在旧的连接传送的、已经没有意义的、过时的TCP报文段(因为这个TCP报文段的序号有可能正好处于新的连接所使用的序号范围内)。因为必须使得迟到的TCP报文段的序号不在新的连接中使用的序号范围内。所以,TCP在建立新的连接时所选择的初始序号一定要和前面的一些连接所使用过的序号不一样。因此,不同的TCP连接不能使用相同的初始序号。

(7)在使用TCP传输数据时,如果有一个确认报文段丢失了,也不一定会引起与该确认报文段对应的数据的重传。试说明理由。

答:这是因为发送方可能还未重传时,就收到了更高序号的确认。例如主机A连续发送两个报文段,均正确到达主机B。B连续发送两个确认ACK1和ACK2(ACK2的序号比ACK1的序号高)。但前一个确认帧在传输时丢失了。若在超时前,ACK2被A接收,更高的序号代表该序号之前的所有字节都被接收了,所以A知道前一个报文也被正确的接收了,这种情况下A不会重传第一个报文段。

 

 

 

 

 

 

 



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有