数据传输的可靠性主要可以分为以下几个方面:
- 数据内容不出错
- 不乱序
- 不重复
- 不丢包
如何保证不出错
校验和
将数据段分为多个16位的整数,进行相加
前面的进位补在后面,最后取反,得到校验和
发送方在发送数据前计算校验和,接收方收到数据后以同样的方式计算
若校验和不一致,则数据传输一定有误
如何保证不乱序、不重复、不丢包
累积确认(ACK)和序列号(seq)
在进行TCP传输时,根据字节对报文段进行编号,作为头部seq字段的值
每次接收方收到数据后,都会返回确认应答,若返回ACK(n),则说明序列号小于n的报文段都已经被成功接收,并表示期望下一个报文段的序列号为n
同时,接收方可以根据序列号对报文段进行排序,去除具有相同序列号的数据
超时重传
发送方在发送完数据后,若在设定的时间内没有收到ACK应答,就重新发送刚刚的数据
(若发送方收到的ACK最大值为n,则从序列号为n的数据开始 进行重新传输)
流量控制
如果发送方的发送速度太快,可能会导致接收方的接收缓冲区很快被填满
之后到达接收方的数据都会丢包,这样就会引起大量的超时重传
因此,在TCP报文段的头部维护一个名为“Receive Window”的字段
用于表示接收方的接收缓冲区的剩余大小
接收方在返回ACK应答时,将自己的即时窗口大小填入,连同ACK报文一起发送过去
发送方根据窗口大小的值,调整自己的发送速度
如果发送方收到ACK后,发现Receive Window值为0,就会停止发送数据
并定期向接收方发送窗口探测数据段,询问接收方的窗口大小
拥塞控制
如果在网络拥堵的情况下,发送方仍然发送大量数据,就会加剧网络的拥堵,造成大量的丢包
因此,TCP引入了慢启动的机制
发送方维护一个拥塞窗口(cwnd),用于限制发送速率(cwnd越大,每次可发送的数据量越大)
刚开始传输时,让cwnd从1个MSS开始,以指数级的速度增长
同时设定一个阈值,当cwnd超过阈值时,转变为线性增长
还有以下2种情况会马上调整cwnd的大小
- 发送方接收到3个冗余的ACK(n):设定阈值为当前cwnd的一半,进入快速恢复模式(快速重传序列号大于等于n的数据)
- 发送方等待ACK超时:说明网络严重拥堵,设定阈值为当前cwnd的一半,并重新开始慢启动