1. 项目概述:流量控制与可靠传输,到底在学什么
如果你正在啃《计算机网络》,不管是谢希仁的第九版、第八版,还是《自顶向下》那本厚得像砖头一样的经典教材,多半都会在一个地方卡住:传输层那一章。三次握手、滑动窗口、流量控制、拥塞控制,这些概念在书里一个接一个地出现,看起来都认识,合上书一问又说不清区别。尤其是"流量控制"和"可靠传输"这两个词,总是绑定在一起出现,但实际学起来却让人觉得像隔了一层纱。
这个专题想要解决的,就是把"流量控制"和"可靠传输"这一整条脉络彻底打通。它不是让你背几个名词,而是真正理解:数据在网络上传输时,发送方怎么知道数据到底有没有送到?接收方处理不过来时怎么让发送方停一停?网络本身就堵的时候发送方又该怎么办?这三个问题分别对应可靠传输、流量控制和拥塞控制,它们互相独立但又协同工作。
从知乎、考研圈的热搜来看,"三次握手"、"滑动窗口"、"慢启动"、"快重传"这些词搜索量一直很高,说明这是几乎所有人在学计网时都绕不开的难点。这篇内容适合的人群很广:正在复习计算机网络期末考的大学生,准备408考研的考生,刚入行做网络开发或者软件测试、需要对网络协议有系统认知的工程师,甚至只是对"为什么我家的网络会卡"产生好奇的普通用户。读完之后,你至少能把书里那些零散的知识点串成一条线,遇到关于可靠传输和流量控制的题能拿分,面试被问到也能讲出所以然。
我的建议是,别把这篇内容当"速成笔记"来刷,而是把它当作一条主线,配合你自己的教材一起看。我会把每个概念背后的"为什么"讲清楚,再结合实际的场景和计算题来演示这些协议到底怎么运转。整个过程不难,关键是建立正确的模型。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 可靠传输的本质:不只是"传到就算成功"
很多同学刚开始学可靠传输时,会觉得这有什么好讲的,就是在数据发出去之后等个确认嘛。但实际上一套可靠传输机制要解决四件事:数据在传输过程中被破坏了怎么办;数据丢失了怎么办;数据到了但顺序乱了怎么办;接收方收到了重复的数据怎么办。这四个问题不解决,任何一个都可能导致应用层拿到错误的数据。所以可靠传输并不是一个简单的"收到就回个ACK",而是一套包含了差错检测、确认、序号、超时重传等机制的完整体系。
2.1 可靠传输的四个关键要素:每一个都必须存在
我先来拆解这四个要素,因为后面讲滑动窗口、讲TCP的可靠传输,全部建立在这四个要素之上。
第一个是差错检测。发送方在把数据包发出去之前,会在末尾附加一个校验码,最常见的算法是校验和(Checksum)。接收方收到数据后,用自己的算法重新算一遍,如果结果和发来的校验码不一致,说明中间某个比特被干扰了,这个包直接丢弃,不回复确认。IP层也有校验和,但只校验头部;TCP/UDP的校验和会覆盖头部加数据部分,检测范围更广。所以应用层拿到的数据,理论上已经是经历过两次差错检测的。
第二个是确认。接收方在正确收到数据后,需要回一个确认报文(ACK),告诉发送方"这个东西我收到了,你可以继续往下发"。没有确认机制,发送方永远不知道数据到底到了没有。
第三个是序号。这是可靠传输里最容易忽略但又极其关键的部分。为什么要序号?想象一下这样一个场景:发送方发了数据包1和2,包1到达后接收方回了ACK,但在回去的路上ACK丢了。发送方等了很久没收到ACK,就超时重传包1。这个时候接收方其实已经收到过包1了,如果接收方不做任何区分,就会把同一个数据交付给应用层两次。有了序号之后,接收方发现"这个序号我处理过了",直接丢弃再重发ACK即可,应用层拿到的是不重不漏的数据。
第四个是超时重传。发送方发出数据后,会启动一个定时器。如果时间到了还没收到对应序号范围的ACK,就认为这个数据包或者ACK丢了,重新发送一遍。这个"超时时间"怎么设置很有讲究:设太短,明明还没慢、只是网络抖动了一下,就会导致一堆没必要的重传,浪费带宽;设太长,一旦真的丢了包,应用层要等很久才能感知到。TCP里这个值是用自适应算法动态估算的,依据是每次往返时间RTT的历史统计值。
这四个要素齐了,才叫"可靠传输"。很多同学在复习时容易忘掉序号的作用,或者答不出"为什么可靠传输需要序号",这其实是一个高频面试考点,值得记牢。
2.2 停止等待协议:最简单但效率最低的可靠传输
理解了四个要素之后,我们先看一种最朴素、书里一定会讲的协议:停止等待协议(Stop-and-Wait)。这个协议的逻辑非常简单:发送方每发一个包,就停下来等ACK;收到ACK再发下一个;如果超时没收到ACK,就重传刚才那个包。
逻辑上它没有任何问题,可靠传输的四个要素它全都有。但效率是它最大的痛点。我来算一笔账。假设发送方和接收方之间的信道速率是1Gbps,往返时延RTT是30毫秒(这差不多是跨省网络的一个典型数值),一个数据包的大小是1000字节,也就是8000比特。发送这个包需要的时间是 8000 ÷ 10^9 = 8微秒。发完之后要等RTT = 30毫秒才能收到ACK。这意味着什么?在整个传输周期约30.008毫秒里,发送方只有8微秒在真正干活,其余时间全都闲着。信道利用率大概是 8微秒 ÷ 30008微秒 ≈ 0.027%,低到可以忽略。
这就是停止等待协议最大的问题:一次只能有一个包在途。别人明明能用很宽的管道运水,你偏偏一桶一桶等着提,管道的容量完全被浪费了。所以在实际系统中,几乎不会直接用这种机制来做高速数据传输。但理解它是理解滑动窗口的起点,因为滑动窗口本质上就是"停止等待协议的流水线版本",让多个包同时"在途",而不是一个个傻等。
2.3 从停等到ARQ:回退N帧与选择重传的取舍
有了"让多个包同时在途"的思想后,自动重传请求(ARQ)机制开始登场。ARQ有三种典型形态:停等ARQ(就是2.2里说的停止等待)、回退N帧ARQ(Go-Back-N,简称GBN)、选择重传ARQ(Selective Repeat,简称SR)。后两者都依赖滑动窗口机制工作,所以这里我需要先把窗口带出来。
GBN的思路是:发送方可以连续发送多个包,接收方只按序接收。如果中间某个包丢了或者出错,接收方会丢弃从这个包开始的后续所有包,并且对最后一个正确接收的包重复发送ACK。发送方一旦超时,就会从那个丢失的包开始,把后面的包全部重传一遍。
GBN的优点是接收方实现简单,不用缓存乱序到达的数据。但缺点是,如果信道质量不好丢包率高,重传的开销会非常大。想象一下发送了100个包,第50个丢了,后面50个都白发了,全都要重来。这在线路本来就不太好的情况下,反而会加剧拥塞。
SR的思路则不同。接收方会根据序号逐个确认,对于乱序到达的包,只要序号对应的缓冲空缺还在,就先缓存起来,不丢弃。发送方只需要重传真正丢失的那个包,其他包不需要动。这样浪费的带宽更少,但代价是:接收方要维护一个较大的缓存区,发送方和接收方都要记录窗口内哪些包已确认、哪些没有,逻辑复杂度明显上升。
这里出现了一个经典的题型:给定发送窗口大小、序号比特位数,比较两种协议的信道利用率和开销。
