tcp保证可靠性的机制

318 阅读4分钟

1、校验和

tcp校验和检验范围包括tcp首部及数据部分

计算方法为:

1)把检验和字段置为0

2)在发送方将整个报文段分为多个16位的段

3)将所有段进行二进制求和,如果高16位不为0,则将高16位和低16位反复相加,直到和的高16位为0,从而得到一个16bit的值

4)将该16bit的值取反,存入检验和字段中

5)接收端用同样方法对16位的段相加,最终得到一个16bit的值,如果最终结果的位全是1(不取反)则正确

2.序列号和确认号

3.超时重传

当报文发出后一定时间内未收到对方的确认,发送方就会进行重传,可能是发送方丢了,也可能是确认的ack丢了

利用序列号可以达到去重的效果

重传时间:报文段发出到收到应答中间有一个报文的往返时间RTT,超时重传时间RTO会略大于这RTT,Linux下,超时时间会动态的发生变化,重传次数累计到一定次数,会强行关闭连接

4.连接管理

TCP三次握手和四次挥手

5.流量控制

解决的是由于发送速率过快导致的丢包问题

接收端处理数据的速度是有限的,如果发送方发送的速度过快,导致接收端缓冲区满,会导致丢包,继而引起重传等一系列连锁反应

tcp首部有个16位窗口长度,接收端会在应答报文ack中将自身缓冲区的剩余大小放入16位窗口长度中

但是发送端会定期发送一个窗口探测,使接收端把窗口大小告诉发送端

6.拥塞控制

如果网络非常拥塞,再次发送可能会加重网络负担,那么发送方的数据段可能超过了最大生存时间也没到达接收方

拥塞控制的五种状态机:open、disorder、cwr、recovery、loss

拥塞控制的四个算法:慢启动、拥塞避免、拥塞发生时、快速恢复

慢启动:

tcp建立初期,一点一点提速,试探网络承受能力

在启动初期以指数增长方式增长;设置一个慢启动的阈值,当以指数增长达到阈值时就停止指数增长,按照线性增长方式增加;线性增长达到网络拥塞时立即“乘法减小”,拥塞串口置回1,进行新一轮的慢启动,同时新一轮的阈值变为原来的一半

1)发送开始时定义拥塞窗口大小cwnd为1;

2)每次收到一个ack应答,拥塞窗口加1;

3)每当过了一个往返延时时间,拥塞窗口大小呈指数上升,乘以2

4)还有一个阈值(ssthresh),当cwnd >= ssthresh时,就会进入“拥塞避免算法”

拥塞避免:

1)收到一个ack,cwnd = cwnd+1/cwnd

2)每当过了一个往返延时时间rrt,cwnd大小加一

过了慢启动阈值后,拥塞便面算法可以避免窗口增长过快导致窗口拥塞,而是缓慢的增加

拥塞状态时:(快重传)

一般来说,tcp拥塞控制默认认为网络丢包是由网络拥塞导致的,所以丢包时认为时网络进入拥塞状态,对于丢包的判有两种方式,一种是超时重传RTO,另一种是收到三个重复确认ack

1)超时重传原理是,在发送一个数据后就开启一个计时器,如果一定时间内没有收到发送数据包的ack,就重新发送,知道发送成功为止

超时重传RTO时,tcp会重传数据包,tcp认为这种情况比较糟糕,所以将慢启动阈值ssthresh设置为当前cwnd的一般,即ssthresh=cwnd/2,cwnd重置为1,进入慢启动过程,但上述机制,一丢包就重置cwnd,不利于网络数据的稳定传送,于是对reno算法进行了优化,tcp开启快速重传算法

2)如果发送端接收到3个以上的重复ack,tcp就认为数据发生丢失,不需要超时重传的定时器,所以叫快速重传

cwnd大小缩小为当前的一半,ssthresh设置为缩小后的cwnd大小,然后进入快速恢复算法

快速恢复:

1)cwnd=cwnd+3MSS,加3MSS的原因时收到了3个重复的ack

2)重传DACKs(重复确认)指定的数据包

3)如果在收到DACKs,那么cwnd大小增加一

4)如果收到新的ack,表明重传的包成功了,退出快速恢复算法,将cwnd设置为ssthresh,然后进入拥塞避免算法

MSS,最大报文段长度。在连接建立的时候,即在发送SYN段的时候,同时会将MSS发送给对方(MSS选项只能出现在SYN段中!!!),告诉对端他期望接收的TCP报文段数据部分最大长度。

参考:

segmentfault.com/a/119000001…

www.cnblogs.com/peanutk/p/1…

blog.51cto.com/lingdandan/…