TCP的重传机制
TCP
实现可靠传输的⽅式之⼀,是通过序列号与确认应答。
在
TCP
中,当发送端的数据到达接收主机时,接收端主机会返回⼀个确认应答消息,表示已收到消息。 但是如果传输的过程中,数据包丢失了,就会使⽤重传机制来解决。
1、超时重传:
设定⼀个计时器,当超过指定的时间后,没有收到对⽅的确认
ACK
应答报⽂,就会重发该数据。
超时重传的两种情况如下:
如果超时重发的数据,再次超时⼜要重传的时候,
TCP
的策略是将超时间隔加倍,也就是
每当遇到⼀次超时重传的
时候,都会将下⼀次超时时间间隔设为先前值的两倍。
2、快速重传:
快速重传(
Fast Retransmit
)机制
,它
不以时间为驱动,⽽是以数据驱动重传
。
⼯作原理:
当收到三个相同的
ACK
报⽂时,会在定时器过期之前,重传丢失的报⽂段。
快速重传解决了超时时间的问题,但还⾯临另外⼀个问题:重传的时候,是重传之前的⼀个,还是重传所有的问题
3、SACK(Selective Acknowledgment,选择性确认):
为了解决 重传哪些报⽂的问题⽽提出。
这种⽅式需要在
TCP
头部「选项」字段⾥加⼀个
SACK
的东⻄,
可以将已收到的数据的信息发送给「发送⽅」
,这样发送⽅就可以知道哪些数据收到了,哪些数据没收到,知道了这些信息,就可以只重传丢失的数据
。
4、D-SACK(Duplicate SACK):
主要使⽤了
SACK
来告诉【发送⽅】有哪些数据被重复接收了。下⾯举例来说明
D-SACK
的作⽤:
ACK
丢包:
网络延时
使⽤
D-SACK
的好处:
(
1
)可以让【发送⽅】知道,是发出去的包丢了,还是接收⽅回应的
ACK
包丢了;
(
2
)可以知道是不是【发送⽅】的数据包被⽹络演示了;
(
3
)可以知道⽹络中是不是把【发送⽅】的数据包给复制了。
TCP的滑动窗口
1. 什么是窗口
TCP
每发送⼀个数据,都需要⼀次应答,然后继续发送,这样为每个数据包都进⾏确认应答,缺点是:数据往返时间越⻓,⽹络吞吐量越低。为了解决这个问题,TCP
引⼊了
窗⼝
这个概念。即使在往返时间较⻓的情况下,它也不会降低⽹络通信的效率。⽽窗⼝的⼤⼩呢,就是⽆需等待确认应答,可以继续发送数据的最⼤值。
假设窗⼝⼤⼩为
3
个
TCP
段,那么发送⽅就可以「连续发送」
3
个
TCP
段,并且中途若有
ACK
丢失,可以通过 「下⼀个确认应答进⾏确认」。如下图:
窗⼝的实现就是操作系统开辟的⼀个缓存空间,发送⽅主机在等到确认应答返回之前,必须在缓冲区中保留已发送
的数据。如果按期收到确认应答,此时数据就可以从缓存区清除。
图中的
ACK 600
确认应答报⽂丢失,也没关系,因为可以通过下⼀个确认应答进⾏确认,只要发送⽅收到了
ACK
700
确认应答,就意味着
700
之前的所有数据「接收⽅」都收到了。这个模式就叫
累计确认或者累计应答。
2. 什么决定窗口大小
TCP
头部有⼀个字段叫
window
,窗⼝⼤⼩。
这个字段是接收端告诉发送端⾃⼰还有多少缓冲区可以接收数据。于是发送端就可以根据这个接收端的处理能⼒来
发送数据,⽽不会导致接收端处理不过来
通常窗⼝的⼤⼩是由接收⽅的窗⼝⼤⼩来决定的。
发送⽅发送的数据⼤⼩不能超过接收⽅的窗⼝⼤⼩,否则接收⽅就⽆法正常接收到数据。
3. 发送方的滑动窗口
下图就是发送⽅缓存的数据,根据处理的情况分成四个部分:
#1
是已发送并收到
ACK
确认的数据:
1
到
31
字节
#2
是已发送但未收到
ACK
确认的数据:
32
到
45
字节
#3
是未发送但总⼤⼩在接收⽅处理范围内(接收⽅还有空间):
46
到
51
字节
#4
是未发送但总⼤⼩超过接收⽅处理范围(接收⽅没有空间):
52
字节以后
下图表示数据全都发送以后,可⽤窗⼝⼤⼩为
0
,在没收到
ACK
确认应答之前⽆法继续发送数据。
4. 程序是如何表示发送⽅的四个部分的呢?
TCP
滑动窗⼝⽅案使⽤三个指针来跟踪在四个传输类别中的每⼀个类别中的字节。其中两个指针是绝对指针(指特
定的序列号),⼀个是相对指针(需要做偏移)
可⽤窗⼝⼤⼩
=
发送窗⼝
-
已发送未确定
(SND.WND -
(
SND.NXT - SND.UNA))
已发送未确认
=
(
SND.NXT - SND.UNA)
5. 接收⽅滑动窗⼝
接收窗⼝根据处理的情况划分成三个部分:
#1 + #2
是已成功接收并确认的数据(等待应⽤进程读取)
#3
是未收到数据但可以接收的数据
#4
未收到数据并不可以接收的数据
其中三个接收部分,使⽤两个指针进⾏划分
:
RCV.WND
:表示接收窗⼝的⼤⼩,它会通告给发送⽅。
RCV.NXT
:是⼀个指针,它指向期望从发送⽅发送来的下⼀个数据字节的序列号,也就是
#3
的第⼀个字节。
指向
#4
的第⼀个字节是个相对指针,它需要
RCV.NXT
指针加上
RCV.WND
⼤⼩的偏移量,就可以指向
#4
的第⼀个字节了。
6. 接收窗⼝和发送窗⼝的⼤⼩是相等的吗?
并不是完全相等,接收窗⼝的⼤⼩是
约等于
发送窗⼝的⼤⼩的。
因为滑动窗⼝并不是⼀成不变的。⽐如,当接收⽅的应⽤进程读取数据的速度⾮常快的话,这样的话接收窗⼝可以
很快的就空缺出来。那么新的接收窗⼝⼤⼩,是通过
TCP
报⽂中的
Windows
字段来告诉发送⽅。那么这个传输过
程是存在时延的,所以接收窗⼝和发送窗⼝是约等于的关系。