TCP既要保证可靠性, 同时又要尽可能提高性能,所以TCP会显得很复杂。
保证可靠性的机制,前几篇已讲过:序列号(按序到达)、确认应答、校验和(华为网络基础 | IP包校验和算法实例抓包验证、华为网络基础 | TCP校验和算法实例抓包验证及华为网络基础 | TCP校验和错误原因及再次实例抓包验证)、连接管理(华为网络基础 | TCP连接管理机制及华为网络基础 | TCP断开连接管理机制),今天继续讲解超时重传机制。
1、什么是超时重传机制?
TCP每发送一个报文段,就会对这个报文段设置一次计时器,只要计时器设置的重传时间到,但发送端还没有收到接收端发来的确认,此时就会重传此报文段。
超时重传机制是内核实现实现的,因为超时重传机制是TCP的一部分,而TCP又属于内核,所以超时重传机制也就是内核实现的
先来看看如下图例:
主机A发送数据给B之后, 可能因为网络拥堵等原因, 数据无法到达主机B;如果主机A在一个特定时间间隔内没有收到B发来的确认应答, 就会进行重发;但是主机A没收到确认应答也可能是ACK丢失了。如图
这种情况下, 主机B会收到很多重复数据,那么TCP协议需要识别出哪些包是重复的, 并且把重复的丢弃,这时候利用前面提到的序列号, 就可以很容易做到去重。
2、为什么在超时重传机制中,计时器设置的时间为什么要变得越来越长?
一个报文段可以好几次的超时,就是说呢第一次发此报文段时超时了,发送端会重新发,第二次发的时候还是超时了,此时发送端还是会重新发送,但是发送端对一个超时的报文段不会一直发,发几次之后,就会丢弃此报文段。
计时器设置的时间在好几次的发送中,为什么要变得越来越长呢?因为在发送数据的时候,数据传输可能还没建立好,此时就重传,可能会浪费资源。
3、超时时间如何确定?
最理想的情况下, 找到一个最小的时间, 保证 “确认应答一定能在这个时间内返回”,但是这个时间的长短, 随着网络环境的不同, 是有差异的,如果超时时间设的太长, 会影响整体的重传效率; 如果超时时间设的太短, 有可能会频繁发送重复的包。
TCP为了保证任何环境下都能保持较高性能的通信, 因此会动态计算这个最大超时时间。
Linux中(BSD Unix和Windows也是如此), 超时以500ms为一个单位进行控制, 每次判定超时重发的超时时间都是500ms的整数倍。
如果重发一次之后, 仍然得不到应答, 等待 2*500ms 后再进行重传. 如果仍然得不到应答, 等待 4*500ms 进行重传,
依次类推, 以指数形式递增,累计到一定的重传次数, TCP认为网络异常或者对端主机出现异常, 强制关闭连接。