计算机网络学习笔记:TCP可靠传输实现、超时重传时间选择
文章目录
- 一、TCP可靠传输实现
- 二、TCP超时重传时间选择
一、TCP可靠传输实现
TCP可靠传输的实现,主要基于发送方和接收方的滑动窗口,以及确认机制:
- 发送方在未收到确认(ACK)前,可以将序号落在发送窗口内的数据段连续发送,但这些数据段必须保留在缓存中,不能释放,以便在超时或接收到重复 ACK 时进行重传。发送方的 滑动窗口表示 “允许发送但未确认” 的数据范围;TCP 不会等待一个 ACK 才发送下一个段,而是可以 “流水线” 式发送多个段;
- 接收方在接收到发送方发送的报文后,要及时发送确认报文,如果接收到的报文段是不连续的,则会对连续报文段的最大序号及之前的数据进行确认。可以对发送方的滑动窗口大小进行调整(流量控制)。
对于发送方和接收方的滑动窗口,都有前沿
和后沿
的概念:
- 发送方:
- 后沿:已发送并且接收到确认报文的数据,可以删除。
- 前沿:在滑动窗口的最大范围之外,不允许发送。
- 接收方:
- 后沿:已发送确认报文给发送方,并且这部分内容交付了应用进程,可以删除。
- 前沿:在滑动窗口的最大范围之外,不允许接收。
为了维护发送窗口的状态,可以使用P1,P2,P3三个指针:
- P1:指向的是发送窗口内已发送,但是还未收到确认的部分的第一个数据的序号。
- P2:指向的是发送窗口内还未发送的部分的第一个数据的序号。
- P3:指向的是发送窗口外的部分的第一个数据的序号。
假设下图的场景:
- 发送方已经成功发送了
4、5、6
三个报文段; - 接收方只成功收到了
5、6
,但没有收到 4; - TCP 默认使用 累计确认(ACK) 策略 —— 只能确认连续收到的数据段。
此时接收方收到的ACK应该为4,同时对5,6进行缓存。这种情况并不会引起发送方的快重传,因为是第一次重复确认
此时接收方收到了4的报文段,则反馈给发送方7的ack,表示已经接受到了4~6的报文段,现在要接受7的报文段,同时窗口向前滑动:
假设此时发送方向接收方发送了7~10号报文段,但是接收方一直都没有ack,因为窗口内的序号已经用完了,发送方在接收到接收方的确认之前,不能发送新的数据,而如果一直接收不到接收方的确认,就会触发超时重传(慢开始 + 拥塞避免算法)
二、TCP超时重传时间选择
RTT = 请求的往返时间 = 请求开始时间 - 接收到请求确认的时间。RTO则是超时重传的时间。RTO不能小于RTT,也不能远大于RTT的值,应设置为略大于RTT的值。
然而上述只是理想情况下的设置,实际网络通信中,每次消息往返的时间都是不固定的,需要动态进行调整。
RTT的计算也是非常复杂的,当发送方发生超时重传的时候,无法知道接收方发出的确认报文段是针对原报文段的确认,还是重传报文段的确认。(应是对于重传报文段的确认)如果发送方将该报文段当做是对于原有报文段的确认,那么算出的RTT往返时间就会大于应有的值。
同理,接收方在发送确认报文段发生了超时,导致发送方触发了超时重传。发送方无法知道接收方的确认报文段,是针对发送方第一次发送的报文的确认,还是超时重传报文的确认(应该是对于发送方第一次报文的确认。)那么算出的RTT往返时间就会小于应有的值。
针对上述的问题,提出了一种karn算法。Karn 算法是用于 计算 TCP 中的往返时间(RTT)和重传超时时间(RTO) 的一个改进方法,专门用来避免因重传而导致的 RTT 估算不准确问题。其核心思想在于不要用重传报文段的 ACK 来更新 RTT 估算值。
- 当发生重传时,不更新 RTT 估计值。
- 只用未发生重传的报文段的 ACK 来估计 RTT。
- 启用
指数退避
策略,即每次重传失败后,将 RTO 值加倍。