- 确认应答机制
TCP将每个字节的数据都进行了编号,即为序列号。每一个ACK都带有对应的确认序列号,意思是告诉发送者收到了哪些数据,下次从哪里发送 - 超时重传机制
- 超时重传机制的工作过程
主机A发送数据给B后,可能因为网络拥堵等问题,数据无法到达主机B。如果主机A在一个特定时间间隔内没有收到B发来的确认应答,就会进行重发。但是,主机A未收到B发来的去人应答,也可能是因为ACK丢失了,因为主机B会收到很多重复的数据。那么TCP协议需要能够识别出哪些包是重复的,并且把重复的丢掉,这时候可以利用序列号就可以很容易做到去重的效果。 - 如何确定超时时间
最理想的情况下找到一个最小的时间,保证“确认应答”一定能在这个时间内返回。但是,这个时间的长短随着网络环境的不同时有差异的 ,如果超时时间设置的太长会影响整体的重传效率;如果超时时间设置的太短,有可能会频繁的发送重复的包。
TCP为了保证无论在任何环境下都能就比较高性能的通信,因此会动态计算这个最大超时时间。Linux中超过500ms为一个单位进行控制,每次判定超时重发的超时时间都是500ms的整数倍。如果重发一次之后仍然得不到应答,等待2500ms后进行重传;如果仍然得不到应答,等待4500ms再重传,以此类推,以指数形式递增。累积到一定的重传次数,TCP认为网络或对端主机出现异常,并强制关闭连接。
- 超时重传机制的工作过程
- 滑动窗口
- 为什么需要滑动窗口?
前面讨论了确认应答策略,对每一个发送的数据段都要给一个ACK确认应答,收到ACK后再发送下一个数据段。这个做法有一个比较大的缺点就是性能较差,尤其是数据往返的实践较长的时候。既然这样一发一收性能较低,那么一次发多条数据,不是就可以将多个段的等待时间重叠在一起提高性能了吗 - 工作过程
窗口大小指的是无需等待确认应答而可以继续发送数据的最大值,规定发送前4个段的时候,不需要等待任何ACK直接发送。收到第一个ACK后,滑动窗口向后移动,继续发送第5个段的数据,以此类推。操作系统内核为了维护这个滑动窗口,需要开辟发送缓冲区来记录当前还有哪些数据没有应答,只有确认应答的数据才能从缓冲区删掉,窗口越大网络吞吐率就越高。那么如果出现丢包,如何进行重传?- 情况1:数据包已抵达,ACK丢了
这种情况下,部分ACK丢了并不要紧,因为可以通过后续的ACK进行确认 - 情况2:数据包直接丢了
当某一个段报文丢失之后,发送端会一直收到1001这样的ACK,就像是在提醒发送端:接收端想要的额是1001“一样。如果发送端主机连续三次收到了同样一个”1001“,就会将对应的数据1001-2000重新发送。这个时候接收端收到了1001之后,再次返回ACK就是7001了,因为2001-7000接收端之前已经收到了,被放到了接收端操作系统内核的接收缓冲区中。这种机制被称为”高速重发控制“,也被称为”快重传“
- 情况1:数据包已抵达,ACK丢了
- 为什么需要滑动窗口?
- 流量控制
- 什么是流量控制
接收端处理出具的速度是有限的,如果发送端发的太快,导致接收端的缓冲区被填满,这时候如果发送端继续发送就会造成丢包,继而引起丢包重传等等一系列连锁反应。因此,TCP支持根据接收端的处理能力来决定发送端的发送速度,这个机制就叫做流量控制 - 工作流程
接收端将自己可以接收的缓冲区大小放在TCP首部中的“窗口大小”字段,通过ACK端通知发送端。窗口大小字段越大,说明网络的吞吐量越高。接收端一旦发现自己的缓冲区快满了,就会将窗口大小设置成一个更小的值通知给发送端,发送端接收到这个窗口之后就会减慢自己的发送速度。如果接收端缓冲区满了就会将窗口置为0,这是发送端不再发送数据,但是需要定期发送一个窗口探测段,使接收端把窗口大小告诉发送端。 - 接收端如何把窗口大小告诉发送端
在TCP首部中,有一个16位窗口字段就是用于存放窗口信息的。16位数字最大表示65535,那么TCP窗口的大小就是65535字节么?实际上,TCP首部40字节选项中还包含了一个窗口扩大因子M,实际窗口大小是窗口字段的值左移M位。
- 什么是流量控制
- 拥塞控制
- 拥塞控制的必要性
虽然TCP有了滑动窗口这个大杀器,能够高效可靠的发送大量数据,但是如果在刚开始阶段就大量的发送数据,仍然可能引发问题。因为网络上有很多的计算机,可能当前网络状态就已经比较拥堵,在不清楚当前网络状态贸然发送大量的数据,是很有可能雪上加霜的。 - 慢启动
TCP引入慢启动机制,先发少量的数据探探路,摸清当前的网路拥堵状态再决定按照多大的速度传输数据。此处引入一个概念——拥塞窗口,发送开始的时候,定义拥塞窗口大小为1,每次收到一个ACK应答拥塞窗口就加1,每次发送数据包的时候将拥塞窗口和接收端主机反馈的窗口大小作比较,取较小的值作为实际发送的窗口。 - 慢启动阈值
向上面这样的拥塞窗口的增长速度是指数级别的。“慢启动”只是在初始的时候慢,但是增长速度非常快。为了不增长那么快,因此不能使用拥塞窗口单纯的加倍。此处引入一个叫做慢启动阈值,当拥塞窗口超过这个阈值的时候,不再按照指数方式增长,而是按照线性方式增长。当TCP开始启动的时候,慢启动阈值等于窗口的最大值,而是按照线性方式增长。当TCP开始启动的时候,慢启动阈值等于窗口的最大值,在每次超时重发的时候,慢启动阈值会变为原来的一般,同时拥塞窗口置回1。少量的丢包仅仅是触发超时重传,大量的丢包就会认为是网络拥塞。当TCP通信开始后,网络吞吐量会逐渐上升,随着网络发生拥堵,吞吐量会立刻下降,拥塞控制。归根结底是TCP协议想尽可能快的把数据传输给对方,但是又避免给网络在成太大的压力的折中方案。
- 拥塞控制的必要性
- 延迟应答
如果接收端数据的主机立刻返回ACK应答,这个时候返回的窗口可能性比较小。假设接收端缓冲区为1M,一次收到了500K的数据,如果立刻应答,返回的窗口大小就是500K。但是实际上,可能处理端处理的速度很快10ms之内就把500k数据从缓冲区消费掉。在这种情况下,接收端处理还远没有达到自己的极限,即使窗口再放大一些,也能处理过来。如果接收端稍微等一会再应答,比如等待200ms再应答,那么这个时候返回的窗口大小就是1M。注意:窗口越大,网络吞吐量就越大,传输效率就越高,应在保证网络不拥塞的情况下尽量提高传输效率。那么所有的包都可延迟应答么?肯定不行,因为规定有数量限制,每隔N个包就应答一次;而且有时间限制,超过最大延迟时间就应答一次,具体的数量和时间依操作系统不同也有差异,一般N取2,超时时间取200ms。 - 捎带应答
在延迟应答的基础上,很多情况下客户端服务器在应用层也是“一发一收”的,意味着客户端给服务器说了“how are you”,服务器也会给客户端一个“Fine,thanks”,那么这个时候ACK就可以搭顺风车在和服务器回应的“Fine,thanks”一起回给客户端。
转载链接https://blog.csdn.net/m0_38121874/article/details/82914634