网络是不可靠的,所以在TCP协议中通过各种算法等机制保证数据传输的可靠性。生活中如何保证消息可靠传输的,那么就是采用一发一收的方式,但是这样其实效率并不高,所以通常采用的是累计确认或者累计应答。
如何实现一个靠谱的协议?
TCP为了保证顺序性,每个包都有一个ID,这个是建立连接之后开始使用的ID,一般确认包都是采用累计确认或者累计应答的模式。
发送端和接收端需要记录已经发送和处理确认的包的记录。
主要几种情况:
- **已确认:**发送端已经发送,接收端已经确认。
- **处理中:**发送端已经发送,接收端正在处理。
- **等待发送:**发送端准备发情,接收到准备接收。
- **没有发送:**发送端没有发送,接收端没有接收。
我们来聊聊为什么还要区分等待发送和没有发送这部分,本质其实为了控制接收端可以处理的数据能力。也就是滑动窗口大小就是接收端的 ,在TCP的保文中接收到会给发送端一个窗口的大小,暗示自己可以处理的数据。如果过多就处理不过来了。 Advertised window
发送端维护的数据结构:
- LastByteAcked 已经确认的数据
- LastByteSent 已发送但是还没有确认的。
- LastByteAcked + AdvertisedWindow 接收端最大处理数据量
接收端维护的数据结构
MaxRcvBuffer:最大缓存的量
LastByteRead 已经接收,但是还没有被应用层读取的。
NextByteExpected 第一部分和第二部分的分界线
顺序问题与丢包问题
假设上面的1,2,3 发送端和接收端已经达成共识,但是 4 ,5发送端还没有接收到,可能丢包了。
接收端8,9已经接收,但是 6,7没有接收,6,7可能丢包了。这种情况其实丢包和顺序问题都出现了,如何解决。
对于丢包问题,采用的是确认与重发机制
也就是设置一定的时间,发送端对于每个发送的包,如果一定的时间没有ACK的话,那么就进行重新发送,这个时间不宜过长和过短,一般是往返时间RTT。但是RTT也是TCP会进行算出一个平均值。也就是自适应重传算法。Adaptive Retransmission Algorithm。
但是对于再次丢包的,TCP 的策略是超时间隔加倍。每当遇到一次超时重传的时候,都会将下一次超时时间间隔设为先前值的两倍。两次超时,就说明网络环境差,不宜频繁反复发送
另一种快速重传的机制是,接收方收到一个大于下一个期望的报文段时,检测数据流中的一个间格。发送三个冗余的ACK,客户端收到后,就在定时器之前,重传丢失的报文端。
丢包问题采用的是确认机制,而顺序问题是通过序号确认的。
流量控制问题
流量控制其实在发送TCP报文的时候,就会携带一个窗口的大小。
会实时的根据接收方的数据大小进行调整,当接收方的处理增大是,发送方会增加可发送的数据,如果缩小,那么发送方就停止发送。
发送方会定时发送窗口探测数据包,看是否有机会调整窗口的大小。这个其实就是流量控制。
拥塞控制问题
流量控制是担心发送方把接收方缓存塞满,而拥塞控制是担心网络塞满。
LastByteSent - LastByteAcked <= min {cwnd, rwnd} ,是拥塞窗口和滑动窗口共同控制发送的速度。
水管有粗细,网络有带宽,也即每秒钟能够发送多少数据;水管有长度,端到端有时延。在理想状态下,水管里面水的量 = 水管粗细 x 水管长度。对于到网络上,通道的容量 = 带宽 × 往返延迟。
TCP 的拥塞控制主要来避免两种现象,包丢失和超时重传
网络拥塞的判定?
- 当网络发生拥塞时,路由器就会丢掉分组,因此,只要发送端没有按时收到应当到达的确认报文 ack,就可认为网络出现了拥塞
慢启动(2的N次增加)-拥塞避免(回退到一半窗口大小 +1操作) 当出现丢包 快速重传和快速恢复解决
快重传
- 快重传算法规定:发送端只要一连收到三个重复 ack,即可断定有分组丢失,就应该立即重传丢失的报文,而不需要等待为该报文设置的重传计时器超时。
- 与慢开始不同,拥塞窗口不设为 1,,而设为慢开始门限+3*mss(mss:最大报文段)。
流量控制和拥塞控制的理解吗?
流量控制考虑点对点的通信量的控制,也就是客户端和服务端直接数据传输数据量的大小。
拥塞控制考虑的问题是整个网络,是全局性的考虑。
小结
顺序、丢包、流量控制是通过滑动窗口来解决的。而拥塞控制是通过拥塞窗口来解决的,不能太快,也不能太慢,需要寻找到中间值。