前置芝士
在讲解 TCP 可靠传输之前,我们先搞清楚什么是 TCP 可靠传输?
TCP 可靠传输就是保证接收方收到的字节流和发送方发出的字节流是完全一样的。
那为什么需要 TCP 的可靠传输呢?
由于网络层是没有可靠传输机制的,尽自己最大的努力进行交付。而传输层使用 TCP 实现可靠传输,TCP 保证可靠传输的机制有如下几种:
1)校验和
2)序列号和确认应答机制
3)重传机制
4)滑动窗口
5)流量控制
6)拥塞控制
校验和
所谓 TCP 的校验和(Checksum)就是说:由发送端计算待发送 TCP 报文段的校验和,然后接收端对接收到的 TCP 报文段验证其校验和(TCP 的校验和是一个端到端的校验和)。其目的是为了发现 TCP 的首部和数据在发送端到接收端之间是否发生了变动。如果接收方检测到校验和有差错,则该 TCP 报文段会被直接丢弃。
序列号和确认应答机制
TCP 报文段的首部中有一个序号字段指的是该报文段第一个字节的序号(一个字节占一个序号)。确认应答机制就是接收方收到 TCP 报文段后就会返回一个确认应答消息,就像下图这样:
重传机制
上面只是简单的介绍了校验和、确认应答机制,下面的重头戏开始了。
上面我们介绍了序列号和确认应答机制,但是错综复杂的网络,并不一定能如上图那么顺利能正常的数据传输,万一数据在传输过程中丢失了呢?
那对于 TCP 针对数据包丢失的情况,会用重传机制解决。下面介绍几种常见的重传机制:
- 超时重传
- 快速重传
- SACK
下面我们逐个击破。
超时重传
超时重传就是在发送数据的时候,设定一个定时器,当超过指定的时间后,没有收到对方的 ACK
确认应答报文,就会重发该数据。一般在下面两种情况下会发生超时重传:
- 数据包丢失
- 确认应答丢失
我们知道了超时重传,那这个超时时间设置为多少比较合适呢?
先介绍一下 RTT(Round-Trip Time 往返时延),如下图:
RTT
就是数据从网络的一端传送到另一端所需的时间两倍,也就是包的往返时间。
超时重传时间是以 RTO
(Retransmission Timeout 超时重传时间)表示。
假设在重传的情况下,超时时间 RTO
较长或较短时,会发生什么事情呢?
简单说一下图中的情况:
- 当超时时间 RTO 较大时,重发就慢,丢了老半天才重发,没有效率,性能差。
- 超时时间 RTO 较小时,会导致可能并没有丢就重发,于是重发的就快,会增加网络拥塞,导致更多的超时,更多的超时导致更多的重发。
由此可见,我们应该设置超时重传时间 RTO 的值应该略大于报文往返 RTT 的值。这样就能确定丢包了,也不会导致丢了老半天才重发。但是这个只是我们想的理论值而已,实际的网络情况比这个复杂的多,有兴趣的同学可以自己的多了解。
如果我们超时重传的数据又超时了该怎么办呢?TCP 的策略是重传的超时间隔加倍。每进行一次超时重传,都会将下一次重传的超时时间间隔设为先前值的两倍。但是这样也会有问题,就是超时时间可能会很长,有没有更快的方式呢?没错