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报文段数据部分最大长度。
参考: