TCP如何保证可靠传输
一、超时重传机制
TCP
服务必须能够重传超时时间内未收到确认的TCP
报文段。为此,TCP
模块为每个TCP
报文段都维护一个重传定时器,该定时器在TCP
报文第一次被发送时启动。如果超时时间内未收到接收方的应答,TCP
模块将重传TCP
报文段并重置定时器。至于下次重传的超时时间如何选择,以及最多执行多少次重传,就是TCP
的重传策略。
Linux
有两个重要的内核参数与TCP
超时重传相关:/proc/sys/net/ipv4/tcp_retries1
和/proc/sys/net/ipv4/tcp_retries2
,前者指定在底层IP
接管之前TCP
最少执行的重传次数,默认值为3;后者指定连接放弃前TCP
最多可以执行的重传次数,默认值为15。
我们来看看CentOS7 Linux
操作系统中这两个参数大小:
时间间隔依次为0.2s、0.4s、0.8s、1.6s和3.2s,每次重传超时时间都增加一倍。在5次重传均失败的情况下,底层的IP
和ARP
开始接管。
二、确认应答机制
回忆TCP
的头部信息:
头部信息中有一个32位序号字段,一次TCP
通信(从TCP
连接建立到断开)过程中某一个传输方向上字节流每个字节的的编号。
假设A主机和B主机进行TCP
通信,A发送给B的第一个TCP
报文段中,序号值被系统初始化为某个随机值ISN
(Initial Sequence Number, 初始序号值)。那么在该传输方向(从A到B),后续的TCP
报文段中序号值将被系统设置成ISN
加上该报文段所携带数据的第一个字节在整个字节流在的偏移。
例如,某个TCP
报文段传送的数据是字节流在的第1025~2048字节,那么该报文段的序号值就是 ISN+1025。另一个传输方向(从B到A)的TCP
报文段的序号值也有相同的含义。
32位确认序号:用作对另一方发送来的TCP
报文段的响应。其值是收到的TCP
报文段的序号值加1。假设A主机和B主机进行TCP
通信,那么A发送出的TCP
报文段不仅携带自己的序号,而且包含对B发送来的TCP
报文段的确认序号。反之,B发送出的TCP
报文段也同时携带自己的序号和对A发送来的报文段的确认序号。
三、滑动窗口机制
TCP
头部信息中有一个16位窗口大小,是用来告诉对方本端还能的TCP
接收缓冲区还能容纳多少字节的数据。
对TCP
的滑动窗口机制,窗口大小指的是无需等待确认应答而可以继续发送数据的最大值。
- 发送前四个段的时候,不需要等待任何
ACK
,直接发送; - 收到第一个
ACK
之后,滑动窗口向后移动,继续发送第五个段的数据,依次类推; - 操作系统内核为了维护这个滑动窗口,需要开辟发送缓冲区来记录当前还有那些数据没有应答;只有确认应答过的数据,才能从缓冲区中删掉;
- 窗口越大,则网络的吞吐率就越高。
如果发生丢包,如何解决?
分情况丢包:
1.假如是ACK
丢了,这种情况问题不大,如果收到后面报文的ACK
,就可以知道,该报文之前的全部报文都已收到;
2.假如是数据包丢了,如果本端连续收到对方3个同样的确认应答报文,则进行重发。