TCP流量控制和拥塞控制是一回事吗?¶
面试官问你:TCP为什么既有流量控制又有拥塞控制?很多人第一反应是:不都是控制发送速度吗?其实这两个机制完全不是一回事。流量控制解决的是接收方"吃不消"的问题,拥塞控制解决的是网络"扛不住"的问题。
流量控制¶
你可以把TCP通信想象成两个人传纸条:发送方负责写纸条,接收方负责看纸条。如果发送方写得特别快,而接收方看得特别慢,很快桌子上就堆满了纸条,最后根本来不及处理。网络里也是一样,接收方会给发送方一个缓冲区,用来暂存收到的数据。如果发送速度远远大于处理速度,缓冲区就会被塞满,后续数据只能丢弃。
所以TCP设计了流量控制机制。核心思想非常简单:接收方告诉发送方自己还能接收多少数据。 这个信息记录在TCP报文里的窗口大小,也叫接收窗口(Receive Window)。发送方每次发送的数据量不能超过接收方通告的窗口大小:如果窗口变小,发送方就减速;如果窗口变大,发送方就提速。本质上,这是发送方和接收方之间的协调机制,目的是避免接收方被"撑爆"。
拥塞控制¶
拥塞控制关注的不是接收方,而是整个网络。还是刚才那个传纸条的例子:假设接收方处理能力很强,但中间负责传递纸条的人只有一个,如果所有人都疯狂塞纸条给他,他很快就会忙不过来,最终导致大量纸条丢失。网络也是一样,路由器、交换机、链路带宽这些资源都是有限的。当大量主机同时发送数据时,网络中的队列会越来越长,最终发生丢包,这就是网络拥塞。
为了避免把网络"打爆",TCP引入了拥塞控制。它维护了一个叫拥塞窗口(Congestion Window,简称CWND)的变量。发送方真正能发送的数据量不仅要看接收窗口,还要看拥塞窗口。实际发送窗口等于接收窗口和拥塞窗口中的较小值。 也就是说,就算接收方还能接收大量数据,如果网络当前非常拥堵,拥塞窗口很小,那发送方也只能发送少量数据。
TCP怎么知道网络是否拥塞呢?答案是通过丢包来判断。因为TCP协议本身看不到整个网络状态,所以只能通过结果反推过程。如果发现超时重传或收到大量重复ACK,就会认为网络可能已经拥塞了,于是主动降低发送速率。
为了实现这一点,TCP设计了四个经典算法:慢启动、拥塞避免、快速重传和快速恢复。
- 慢启动阶段:发送窗口从很小开始,每收到一个ACK就快速增长。这样做是为了先试探网络容量。
- 拥塞避免阶段:等窗口增长到一定程度后,增长速度变慢,避免把网络一下撑爆。
- 快速重传和快速恢复:如果出现丢包,说明网络已经接近极限,就触发这两个机制,主动降低发送速率,然后重新探测网络容量。
总结¶
- 流量控制解决的是发送方和接收方之间的速度匹配问题,防止接收方缓冲区被塞满,它依赖的是接收窗口。
- 拥塞控制解决的是整个网络资源不足的问题,防止网络出现大规模丢包,它依赖的是拥塞窗口。 一个关注终点,一个关注路途;一个保护接收方,一个保护网络。