TCP的重传机制

        我们都知道基于TCP协议的传输都是相对稳定和安全的,那么它是通过何种方法保证数据的正确性以及安全性呢,其中之一就是因为TCP具有重传机制。由于TCP是基于双方连接的,因此需要接收端和发送端保证连接之后才会发送有效信息,所以在介绍TCP的重传机制之前先介绍TCP是怎样保证连接性的,即TCP的三次握手

        TCP的三次握手: 三次握手的目的是保证客户端和服务器端都同时具有发送和接收的功能,具体的步骤如下。

        1,客户端发送连接请求包syn和一个序列号seq到服务器,自身进入发送请求状态

        2,服务器端接收到客户端发送的syn请求包后必须进行确认,并回应一个syn包和确认包ACK以及序列号seq+1,自身进入接收请求状态

        3,客户端收到服务器的回应之后会发送一个ACK确认包,自身进入已连接状态

        4,服务器端收到客户端发送的ACK确认包后自身进入已连接状态,完成三次握手

        在上述描述中客户端是主动进行连接,而服务器端是在收到客户端的连接请求之后被动进入连接 

 具体解释图如下:

          通过这样的三次握手,客户端与服务端建立起可靠的双工的连接,开始传送数据。三次握手的最主要目 的是保证连接是双工的,可靠更多的是通过重传机制来保证的,而所有的重传机制都是依赖于序列号seq以及确认应答ACK。所以解释以下什么是序列号和ACK。

        在使用TCP进行数据传输时每个消息都有带有TCP协议的包头,在包头中就存在seq序列号和ACK确认包。

seq(Sequence Number):32bits,表示这个tcp包的序列号。tcp协议拼凑接收到的数据包时,根据seq来确定顺序,并且能够确定是否有数据包丢失。

ack(Acknowledgment Number):32bits,表示这个包的确认号。首先意味着已经收到对方了多少字节数据,其次告诉对方接下来的包的seq要从ack确定的数值继续接力。

在三次握手中:

  • 起始包的seq都等于0
  • 三次握手中的ack=对方上一个的seq+1
  • seq等于对方上次的ack

        常见的重传机制主要有以下几种:

                超时重传

                快速重传

                SACK

                D-SACK

         例如在正常传输过程中过程如下:

         客户端将带有用户数据的包发送给服务器,序列号seq = 1,服务器收到该数据包后进行确认,ACK的值为数据包的seq值+1代表下一个包的序列号,因此 客户端需要发送的下一个数据包的seq值为服务器回应的ACK+1。

        超时重传 

                假如客户端一共发送了五个包,序列号分别为1,2,3,4,5,假如第三个包在传输过程中失败了那么服务器只收到了1,2,所以回应的ACK为3,但是下次一收到的包的序列号seq为4,该序列号显然不是服务器所期待的因此便不再回应ACK直到发送端发送期待的序列号为止。在发送端这边由于自己已经将序列号seq = 3的包发送出去因此一直在期待对方回应ACK = 4,但是却没有收到,这时双方就开始摆烂了,两个都不发。因此重传就能够打破这种僵局,由发送端再发送一次丢失的包即可。而重发也需要一定的条件,在实际情况中在一定的时间间隔内不管是因为发送端的数据未到达或者是接收端未回应ACK都会造成消息的重传。如下图在RTT的时间间隔内如果发送端没有收到确认信息就会进行消息重传,如果RTO较长就会造成网络延迟,导致接收方在很久之后才会收到对应的包,但是在这个时间段内发送方由于长时间未接收到该包的ACK,因此会进行重传,就会造成同一个包重复被发送。

        这时又出现两种重传的情况:

                (1) 发送端重传丢失的包即可

                (2) 发送端重传丢失之后的所有包

        因为发送端并没有接收到发送失败的那个包之后的ACK,因此它就会认为所有的包都丢了,所以会将错误后的所有包都进行重传,但实际情况并不是它想的那样,而是只有一个包发生了错误。所以这种方法比较浪费资源,这种是比较简单的超时重传。

快速重传

        快速重传不以时间作为重发的判断条件,而是以收到的ACK的重复次数作为判断条件。

        如果接收端没有收到自己所期望数据包就会一直发送上一次的ACK,发送三次后发送端便进行重传。例如,发送端发送分别发送1,2,3,4,5五个包,假如第二个包由于某种原因丢失了,那么由于第一个包是成功发送的所以接收端回应的ACK为2,但是一直没有收到这个包,因此便会在发送端发送其他包过来时也一直回应ACK = 2,直到发送了三次,发送端这才直到接收端是没有收到第二个包,于是便会重传,由于3,4,5,在这个过程中已经发送到了接收端,接收端也已经收到了,所以在第二个包被重传之后接收端便会回应ACK = 6。

        但是也有一个问题就是重传的时候是否只需要重传出错的这个还是重传从错误的这个开始之后的所有数据,因为在收到接收端重复回应的ACK时并不知道是对哪一个包的回应。

SACK(selective Acknowledge) 选择性确认

         SACK在快速重传的基础上,接收端会返回最近收到的报文段的序列号范围,这样发送端就知道,哪些数据包已经到达接收端了。

        如下图,发送方收到了三次同样的 ACK 确认报文,于是就会触发快速重发机制,通过 SACK 信息发现只有 200-299这段数据丢失,则重发时,就只选择了这个 TCP 段进行重复。

        DSACK (Duplicate SACK) 重复发送SACK

         DSACK这个机制是在 SACK 的基础上,额外携带信息,告知发送方有哪些数据包自己重复接收了。DSACK 的目的是帮助发送方判断,是否发生了包失序、ACK 丢失、包重复或伪重传。让 TCP 可以更好的做网络流控。

        由于发送方之前发送的两个包都没有得到回应,当时间到达RTT后发送方便进行重发,但是接收方已经接收过该包了只是发送方没有收到ACK而已,因此接收方回应的ACK为最新数据的ACK,这时发送方收到回应信息后便知道之前的消息对方是接收到了只是回应的 ACK丢失了。

        网络延迟:

          由于1000-14999的数据包被网络延迟造成未按时到达,在其他的包到达时接收方便会一直回应ACK = 1000表示没收到这个包,因此发送方便会进行重传,但是当网络延迟结束之后1000-1499包才到达接收端,这时接收方回复的ACK已经到了3000,明显这个包应该在之前就应该到达了,因此便发送了一个SACK,因此该SACK是DSACK,用于供发送方判断出现该情况的原因。

猜你喜欢

转载自blog.csdn.net/guishangppy/article/details/127055770