先记住这个答案
TCP将数据分成带32位序列号的段,接收方以确认号反馈期望的下一字节序号,从而表示此前数据全被收到。发送方若超时未收到确认或收到三次重复确认,则重传该段。校验和用于发现传输中发生的比特损坏,损坏的段被丢弃并因未确认而再次触发重传。接收方依据序列号对乱序段排序并丢弃重复段,最终向应用层递交完整有序的数据。
- ACK确认的是连续字节流位置,并非单段
- 序列号同时承担排序和去重双重职责
- 损坏段被丢弃后依赖重传补发,校验和只负责发现
四种机制分别解决什么问题
TCP将应用层字节流切分成段,每段携带32位序列号,数值代表该段首个字节的位置。接收方收到数据后返回确认号,该值指示期望收到的下一字节序号,等价于宣告此前所有字节已无损到达。发送方由此明确知道哪些数据已被确认、哪些仍需要处理,这是可靠传输的基础闭环。
校验和覆盖TCP头部、伪首部和载荷,接收方重新计算若不一致则整段丢弃且不回复确认,效果等同链路丢失该段,最终会触发发送方重传。接收方将乱序到达的段存入缓存,待缺失段补全后按序列号升序上送;当一个报文因误判被重传两次时,接收方依靠相同序号识别冗余副本并将其丢弃,避免重复数据进入应用层。
带0.8%丢包的文件传输场景
假设参数:单TCP连接传输2GB备份文件,RTT稳定在50ms,随机丢包率约0.8%。发送方连续发出多个段,其中序号范围23456000至23456999的段在途中被丢弃,而后面的段陆续到达。接收方因缺少这一段,对每个后续段返回确认号23457000,累计产生三个重复ACK。发送方据此立即重传该段,而不必等待超时计时器,最终接收方补全并用序列号完成排序。
若该段之后的报文也全部丢失,接收方没有机会产生重复ACK,这时发送方只能依靠RTO超时恢复,而RTO通常被估算为数百毫秒,比RTT高出一个量级。为此可以启用SACK选项,让接收方在确认中列出已收到的连续区间,发送方只需针对空缺区间重传,减少无效传输并缩短恢复时间。这个场景说明选择重传触发方式和补充确认策略能直接改变高丢包链路的完成总时长。
可靠机制的失效条件与工程判断
校验和只能检测单纯的比特翻转,若有多个比特同时出错且恰好使校验结果一致,则会发生漏检,这种概率极低但理论存在。重传算法高度依赖RTO估算,当RTT抖动剧烈时,过小的RTO会导致不必要的重传和带宽浪费,过大的RTO又会让发送方长时间空等,吞吐大幅下降。
工程上可抓包统计重传次数和重复ACK比例,若重传比例显著偏高且链路未拥塞,则应考虑启用SACK或调大RTO下限。可操作的判断点是:看到大量超时重传但重复ACK很少,说明网络偏向静默丢包;反之重复ACK高频出现说明链路乱序或轻微丢包。可靠性机制本身不区分丢包原因,将随机丢包一律当作拥塞处理属于另一种控制逻辑,不在本主题范围内。
容易答错的地方
- ACK表示本段已收到
- TCP的确认号是期望收到的下一字节序号,它确认的是该序号之前所有字节,并不只确认单一报文。若按单段理解会导致实现误判并产生多余重传,正确算法依赖累计确认语义。
- 校验和能保证端到端完整
- 校验和只能发现某些错误,不能纠正,也不能抵御故意篡改。真正恢复依赖发送方重传,同时TCP可选TCP-MD5或TLS来增强完整性,不能单靠校验。
面试官还会怎么问?
TCP如何区分重传段和原本的段?
发送方重传时携带与原段相同的序列号和载荷。接收方根据序列号发现重复到达,直接丢弃副本。网络本身不区分重传,只有接收方的去重逻辑能消除重复。
为什么快速重传在三次重复ACK后才触发?
乱序也会造成少量重复ACK,三次重复的保守阈值可降低误判概率,表示确实缺失了某一段且已有足够后续数据到达,此时重传的收益比继续等待超时更高。
接收方校验和出错不发ACK会怎样?
该段被丢弃,接收方不更新确认号,发送方由于等不到相应确认最终触发超时或依赖后续重复ACK机制重传。应用数据不会丢失,但延迟会增加一拍。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。