MTU和MSS,管【单个TCP包到底发多大最合适】,是整个传输的基础;
RTT和RTO,管【包发出去之后,怎么保证对方一定收到,丢包了怎么办】,是TCP可靠传输的核心;
cwnd和ssthresh,管【一次能连续发多少个包,怎么既跑满带宽,又不把网络堵死】,是TCP拥塞控制的核心。
MTU & MSS
MTU(最大传输单元,Maximum Transmission Unit)
平时用的以太网、WiFi,硬件层面就规定了一个完整的IP数据包,最大不能超过1500字节,这个上限就是MTU。
如果IP包超过MTU,就会被拆成好几个小分片传输,只要有一个分片丢了,整个包就得全量重传,特别影响效率,还可能被防火墙拦截。
MSS(最大报文段长度,Maximum Segment Size)
这是基于MTU算出来的、TCP包里真正能装的业务数据的最大长度——要把IP头、TCP头的空间提前扣掉。
以太网默认MTU1500字节,标准IP头和TCP头各占20字节,所以默认MSS就是1460字节。
它是TCP三次握手的时候,客户端和服务端协商出来的,最终取两边的最小值,目的就是从源头避免IP拆包。
RTT & RTO
RTT(往返时延,Round-Trip Time)
我发一个TCP包出去,到我收到对方回的【我收到了】的ACK确认包,这一来一回花的时间,就是RTT。
它是网络环境决定的客观值,网络越拥堵、跨的路由越多,RTT就越长,会实时波动,是算RTO的唯一基础。
RTO(重传超时时间,Retransmission TimeOut)
我发出去一个包,会设一个定时器,要是超过这个时间还没收到ACK,我就认为这个包丢了,马上重发一个,这个定时器的时间就是RTO。
RTO完全是基于RTT算出来的,不是固定死的。
它必须比RTT大一点。
如果太小了,ACK还在路上就瞎重传,浪费带宽;
但太大了,真丢包了半天不重传,传输变慢。
所以,网络波动RTT变了,RTO也会跟着实时调整。
cwnd & ssthresh
这两个参数是TCP拥塞控制的核心,TCP刚建连的时候,根本不知道当前网络能扛住多大流量,发少了浪费带宽,发多了直接把网络堵死,所以用这两个参数控制发送节奏。
cwnd(拥塞窗口,Congestion Window)
TCP发送端自己维护的【油门】,单位是MSS。这个参数决定了在没收到对方ACK之前,我最多能连续发多少个包。
比如cwnd=10,就是最多连续发10个MSS大小的包,不用等ACK。
需注意的是,cwnd不是固定的,网络越好、丢包越少,cwnd就越大,发送速度就越快;一旦丢包,就会马上降下来。
ssthresh(慢启动阈值,Slow Start Threshold)
cwnd的【换挡开关】,用来划分两个发送阶段,单位也是MSS。
当cwnd < ssthresh时,进入慢启动阶段,cwnd每过一个RTT就直接翻倍,指数级快速涨速,尽快把带宽跑满;
当cwnd ≥ ssthresh时,进入拥塞避免阶段,cwnd每过一个RTT才加1,线性慢慢涨,避免冲太猛把网络堵死。
一旦检测到网络拥堵丢包,ssthresh会立刻降到当前cwnd的一半,再根据丢包的严重程度调整cwnd,重新控制发送节奏。