TCP可靠性的实现
超时重传
- 超时重传:在数据发送的时候,设定一个定时器,当在设置的时间内没有收到相应的ACK确认应答报文就会重发该报文
超时重传的两种情况
- 数据包丢失
- 确认应答丢失
超时时间的设置
- RTT:就是数据从网络的一端到另一端所需的时间(就是包的往返时间)
- RTO:就是超时计时器计算的祭时间
设置不合理的两种情况
流量控制
滑动窗口
- 窗口实际上是操作系统开辟的一个缓存空间,发送方主机在确认应答的返回之前,必须在缓冲区中保留已经发送的数据,如果如期收到,此时数据就会从缓冲区中清除(多个数据包同时发送,不需要等待)
- 假设窗口的大小为3个TCP报文段,并且中途有ACK丢失,通过下一个应答进行确认(累积确认)
窗口的大小是如何确认的
- TCP头部有一个窗口大小的字段,这个字段是接收端告诉发送方自己还有多少缓存的空间可以接收数据,于是接收端就能根据接收端的接收能力来发送数据,而不会导致接收端处理不来,造成数据包的丢失
发送方的滑动窗口
- #1的区域代表了已经发送并且已经得到接收方确认的数据
- #2的区域代表了已经发送但是还没有收到对方ACK确认的数据
- #3的区域代表了发送方还没有发送但是还能被接收的数据,当这个区域为0的时候,发送方就不能再发送数据
- #4 超过接收方接收范围的数据
滑动窗口区域的确认
- SND.WND:大小有接收方所决定
- SND.UNA:已经发送但是未确认的第一个字节的序号(绝对指针)
- SND.NXT:未发送但在可发送范围内的第一个字节的序号(绝对指针)
- 可用窗口大小:可通过偏移量来计算
接收方的窗口
- #1:已经成功接收并且确认的数据
- #2: 为收到数据但是可以接收的数据
- #3 :为收到数据并不可以接收的数据
窗口的设置
- RCV.WND:表示窗口的大小(根据自己接收能力设定),它会通知给发送方
- RCV.NXT:是一个指针,它指向期望从发送方发送的下一个数据字节的序列号
流量控制的过程
窗口关闭问题
- 窗口关闭:当接收方的接收窗口为0的时候,就会阻止发送方发送数据直到窗口非0为止
带来的问题
解决方案
- TCP为每一个连接都设有一个超时计时器,只要TCP连接一方收到对方零通知窗口就会开启持续计时器
- 窗?探测的次数?般为 3 次,每次?约 30-60 秒(不同的实现可能会不?样)。如果 3 次过后接收窗?还是 0 的话,有的 TCP 实现就会发 RST 报?来中断连接。
拥塞控制
- 原因:当网络出现阻塞的情况下,如果还继续发送大量的数据包,可能会造成数据包的丢失、延时,这时TCP就会重传便会加重网络的负担
拥塞窗口
- 拥塞窗口:发送方维持的一个状态量,它会根据网络的情况进行动态变化
- 发送窗口等于接收方的接收窗口和拥塞接口的最小值
拥塞控制算法
慢开始
- TCP建立初始化会将cwnd设置为1,ssthresh设置为16
- ssthresh(慢开始门限):当cwnd<ssthresh的时候,会使用慢开始算法,当cwnd>=ssthresh的时候会使用拥塞避免算法
慢开始的过程 - 当连接建立之后,一开始初始化cwnd=1,表示可以传一个MSS的数据
- 当接收到一个ACK应答的时候,cwnd就增加1,于是便能够一次发送两个了(直到到达ssthresh之前都是按照指数增长的)
拥塞避免算法
-
规则:每收到一个ACK,cwnd就增加1/cwnd -
例子:先假设ssthresh的值为8 -
当有8个ACK同时到达的时候,cwnd就会增加1,于是便能够发送9个MSS,这样就变成了线性增长 -
随着一直增长下去,网络就会发生阻塞的情况,于是便发生了丢包的事情,这就需要丢失的数据包进行重传,当超时重传的时候就进入到拥塞发生的阶段
拥塞发生
当发生拥塞的时候,就会发生数据包的重传,重传的机制有两种
超时重传的拥塞算法
- 将ssthresh置为cwnd/2
- 将cwnd置为1,重新慢开始
快速重传的拥塞发生
- 将cwnd/2
- 将ssthresh设置为cwnd
- 进入快速恢复算法
快速恢复算法
- 将cwnd设置为ssthresh+3
- 重传丢失的数据包
- 每收到一个重复的数据包就+1;
- 如果接收到了新数据的ACK后,将cwnd设置为第一步的ssthresh的值,原因是丢失的包的数据已经收到,可以恢复到原来的状态,就再次进入到拥塞避免的状态
拥塞避免算法
|