Skip to content

第四章 传输层:TCP、UDP 与可靠传输


1. 传输层为什么存在:从"主机到主机"到"进程到进程"

网络层的 IP 已经能把分组送到目标主机,但一台主机上同时跑着浏览器、微信、网易云,数据到了主机门口,该进哪扇门?这就是传输层要补的最后一公里:把通信从"主机到主机"细化为"进程到进程"

实现手段是端口号:16 位整数(0~65535),标记主机上的一个通信端点。发送方把多个应用的数据汇入网络叫复用,接收方按端口号把数据分发给各应用叫分用。一个通信端点由"IP 地址 + 端口号"唯一确定,这个组合就是套接字(Socket)——IP 找到那栋楼,端口找到那扇门。

常用端口必须背下来,选择题直接考:

端口协议端口协议
20/21FTP 数据/控制53DNS
22SSH80HTTP
23Telnet110POP3
25SMTP443HTTPS

0~1023 是知名端口,留给标准服务;客户端一般使用系统临时分配的高位端口。

传输层只提供两种风格迥异的服务:UDP——几乎什么都不管的"裸奔版",TCP——把可靠性做满的"全险版"。理解二者是本章全部内容。

2. UDP:只加端口号,其余一概不管

UDP(用户数据报协议)在 IP 之上只做最少的两件事:加上端口号实现进程分发,加一个可选的校验和。它的首部只有 8 个字节、4 个字段:源端口、目的端口、长度、校验和。

UDP 的"不作为"清单:不建立连接、不确认、不重传、不排序、不控制发送速度。数据报扔出去就不管了,所以叫"无连接、不可靠"。

但"不作为"恰恰是它的价值:

  1. 没有建连延迟:想发就发,省掉握手来回。
  2. 首部小、开销低:8 字节对 TCP 的至少 20 字节。
  3. 不重传意味着延迟可控:直播丢一帧画面无所谓,等一秒重传反而卡顿。
  4. 保留报文边界:发三次就是三个独立数据报,不像 TCP 把数据搅成字节流。

典型场景:DNS 查询(一问一答,建连不划算)、音视频通话与直播(宁丢勿等)、DHCP(连 IP 都还没有,谈不上建立连接)。

3. TCP 三次握手:为什么恰好是三次

TCP(传输控制协议)提供"面向连接、可靠、有序的字节流"。通信前必须先建立连接——所谓连接不是真拉了一根线,而是双方各自初始化一套状态(序号、窗口、缓冲区),并确认对方已就绪

**为什么恰好三次?**从需求倒推:

  1. TCP 是双向通信,两个方向都要可靠,所以双方都要送出自己的起始序号,也都要收到对方对它的确认——这一共是四件事:C 发序号、S 确认、S 发序号、C 确认。
  2. 两次不够:只完成"C 发、S 确认",服务器发出的序号没得到确认,服务器不知道客户端是否收到、甚至不知道客户端还活着。经典反例是失效的旧连接请求:某个在网络里迷路很久的旧 SYN 姗姗来迟,若两次握手即建连,服务器会为一个早已作废的请求白白建立连接、傻等数据。第三次握手正是让客户端有机会"不认账",废弃的请求得不到第三次确认,连接就建不起来。
  3. 四次浪费:S 的确认和 S 的序号可以合并在同一个报文(SYN+ACK)里捎带,没必要分两次发。

一句大白话点透:三次握手 = 双方各自完成一轮"我说、你答",其中中间那次一箭双雕

4. 四次挥手与 TIME_WAIT

断开连接要四次,多出的一次源于 TCP 的双向独立关闭:你说完了不代表我说完了。

为什么是四次而不是三次?握手时服务器的 ACK 和 SYN 可以合并,因为它当时没有别的事要做;挥手时服务器收到 FIN 后可能还有数据没发完,只能先回 ACK 表示"收到你要关",等自己的数据发完再单独发 FIN,中间隔着一段数据传输,两步合不了。

**为什么主动关闭方要等 TIME_WAIT(时长 2MSL,即报文最大生存时间的两倍)?**两个原因:

  1. 保证最后一个 ACK 送达:如果第四次的 ACK 丢了,服务器会重发 FIN;客户端若已关闭就没人应答,服务器无法正常关闭。等 2MSL 就能接住可能重来的 FIN。
  2. 让旧连接的报文在网络中自然死亡:避免残留报文窜进随后用相同地址端口建立的新连接里造成混乱。

5. TCP 报文段首部:认识几个关键字段

不需要背整个首部,但下面几个字段是理解 TCP 一切机制的"仪表盘",也常出选择题:

字段长度作用
源端口 / 目的端口各 16 位进程到进程的门牌
序号32 位本段第一个字节在字节流中的编号
确认号32 位期望收到的下一个字节编号,即"x 之前的都收齐了"
窗口16 位告诉对方"我还能再收多少",流量控制的载体
标志位各 1 位SYN 请求建连、ACK 确认有效、FIN 请求关闭、RST 强制复位
校验和16 位差错检测,覆盖首部与数据

两个细节:TCP 首部最短 20 字节(UDP 固定 8 字节);序号编的是"字节"而不是"报文段"——TCP 把应用数据看成连续的字节流,逐字节编号,这是它"面向字节流"的直接体现。

6. 可靠传输的四大机制

IP 层会丢包、乱序、出错,TCP 在这样的地基上盖出"可靠",靠的是一套环环相扣的机制:

机制解决什么问题白话原理
序号乱序与重复给每个字节编号,收方按号排序、重复的丢弃
确认 ACK发方怎么知道收到了收方回执"x 号之前的我都收齐了,下次请发 x"
超时重传丢包发出后计时,超时没等到确认就重发
滑动窗口效率不必发一个等一个,允许一批数据"在路上"

前三个保证正确性,容易理解;滑动窗口值得多说一句。如果每发一个段都停下来等确认(停等协议),链路大部分时间在空转。滑动窗口允许发送方连续发出窗口内的多个段,收到确认后窗口向前滑动、继续发新数据——用"流水线"替代"一问一答",把往返时间的浪费摊薄。窗口越大,同时在路上的数据越多,吞吐量越高(直到把网络塞满为止)。

用一个直觉算术感受停等的浪费:假设往返时间 RTT 是 100 毫秒,每次只发 1 KB 就停下等确认,那么每秒最多完成 10 个来回,吞吐量只有 10 KB/s——哪怕线路是万兆光纤也一样,因为瓶颈在"等"而不在"路"。滑动窗口把等待的空档全部填上数据,这就是"高带宽也要配大窗口"的原因。

再补两个机制细节,简答题常用:

  1. 超时时间怎么定:太短会把"路远"误判成"丢了"造成无谓重传,太长又让丢包迟迟得不到补救。TCP 的做法是持续测量 RTT 并动态调整超时值——网络快就把闹钟拧短,网络慢就放宽,自适应而非写死。
  2. 快重传:不必干等超时。接收方每收到一个失序的段就重复发"我还在等 x"的确认,发送方连收三个重复确认即断定 x 号段丢了,立即重传。这比等闹钟响快得多,也是"收到三个重复 ACK"这一考点的出处。

7. 流量控制 vs 拥塞控制:两个刹车,两个理由

TCP 有两套限速机制,考试最爱混着考,必须分清它们怕的对象不同

  1. 流量控制:怕接收方撑死。接收方在每个 ACK 里带上自己的接收窗口(缓冲区还剩多少),发送方发送量不得超过它。这是"点对点的体贴"。
  2. 拥塞控制:怕网络堵死。网络是公共道路,大家都猛发就会在路由器排长队直至丢包。发送方维护一个拥塞窗口,根据网络状况自行调节。这是"对公共资源的自觉"。

实际发送窗口 = min(接收窗口, 拥塞窗口)——两个刹车谁踩得狠听谁的。

拥塞控制的经典策略:

  1. 慢启动:连接刚建立时不知道路况,拥塞窗口从很小起步,但每收到一轮确认就翻倍(指数增长)——名字叫"慢",只因起点低,长得其实飞快。
  2. 拥塞避免:窗口涨到警戒线(慢启动门限)后改为每轮加 1(线性增长),小心试探极限。
  3. 出现丢包:视为拥塞信号,把窗口猛砍(如减半甚至回到起点),门限也调低,然后重新爬升。

这套"线性增、乘性减"合称 AIMD(加法增大、乘法减小),直觉图景如下:

为什么增得慢、减得狠?拥塞的代价是全网共同承担的,宁可保守:小步试探不容易压垮网络,一旦发现堵车立刻大幅退让,长期形成"锯齿波",在效率与公平之间取得平衡——所有 TCP 连接都遵守同一规则,才能公平分享带宽。

丢包信号还分轻重:超时说明网络可能堵得厉害,窗口回到起点重新慢启动;三个重复确认说明后续数据还在陆续到达、网络没有瘫痪,只需把窗口减半后直接进入拥塞避免继续线性爬升——这套温和处理叫快恢复。记忆口诀:超时重头再来,快重传减半继续。

8. TCP vs UDP 全维度对照

维度TCPUDP
连接面向连接,三次握手无连接,即发即走
可靠性确认、重传、排序、去重尽力而为,丢了不管
数据形态字节流,无报文边界数据报,保留边界
顺序保证
流量/拥塞控制都有都没有
首部大小20~60 字节固定 8 字节
传输模式仅一对一支持一对一、一对多、广播、组播
速度与开销开销大,时延较高开销小,时延低
典型应用HTTP、FTP、SMTP、SSHDNS、DHCP、直播、语音、网游

字节流与"粘包"

"面向字节流"值得单独展开一次。应用程序调用三次发送,各发 100 字节,TCP 完全可能把它们合并成一个 300 字节的段发出,接收方一次就读到 300 字节——三条消息"粘"在了一起;也可能拆成 150 + 150 两段。TCP 只承诺"字节不丢、不重、不乱序",从不承诺"你发几次我就收几次"。所以基于 TCP 的应用协议必须自己定义消息边界(比如 HTTP 用头部里的长度字段声明正文多长)。UDP 则没有这个问题:一个数据报就是一条完整消息。

"实时业务一定用 UDP"?——辨析绝对表述

这类说法是考试的经典陷阱,要点有三:

  1. 方向性成立:实时音视频通常倾向 UDP,因为重传旧数据不如播放新数据。
  2. 但"一定"不成立:不少视频网站的点播基于 HTTP(TCP 之上);HTTP/3 的底层 QUIC 虽然跑在 UDP 上,却在应用层自己实现了可靠传输——用了 UDP 不等于放弃可靠性。
  3. 反过来,"可靠场合一定用 TCP"也不绝对:DNS 平时用 UDP,靠"没收到答案就重问"在应用层补足可靠性;响应过大或区域传送时又会改用 TCP。

正确的思维方式:传输层只提供两种原料,可靠性可以在任何一层补做(端到端原则);选谁取决于应用最在乎延迟、开销还是完整性。看到"一定""只能""必然"要条件反射地找反例。

9. 补充视角与例题演练

9.1 一条 TCP 连接由什么唯一确定

答案是四元组:源 IP、源端口、目的 IP、目的端口。四项中任何一项不同,就是不同的连接。由此可以解开两个常见疑惑:

  1. 服务器只开一个 80 端口,怎么同时服务上万个用户?因为每个用户的源 IP 或源端口不同,四元组各不相同,操作系统按四元组把数据分发到对应连接——端口不是"一次只能一人用的电话亭"
  2. 一台客户端可以同时与同一服务器的同一端口建立多条连接,只要本地用不同的源端口。

9.2 例题演练

例题一:主机 A 向主机 B 发送 TCP 报文段,序号为 1001,携带 200 字节数据。B 正确接收后,发回的确认号是多少?

解析:确认号 = 期望收到的下一个字节编号 = 1001 + 200 = 1201。注意不是 1200(最后一个字节是 1200,期望的下一个是 1201),也不是 1001。

例题二:判断:"TCP 的流量控制和拥塞控制是同一机制的两种叫法。"

解析错误。流量控制解决"接收方来不及收",由接收窗口驱动,是双方之间的事;拥塞控制解决"网络承受不住",由拥塞窗口驱动,是对公共网络的自我约束。发送窗口取两者较小值,说明它们是两个独立的闸门。

例题三:某应用要求把用户操作以最低延迟发给服务器,偶尔丢一两条也无妨(如在线游戏的走位同步),应选 TCP 还是 UDP?

解析:选 UDP。理由不是"UDP 更快"这种含糊说法,而是:TCP 的可靠机制会让丢失的旧数据阻塞后续新数据(队头阻塞),游戏宁可要最新位置也不要补发的旧位置;UDP 即发即走、无重传延迟,符合"新鲜度优先"的需求。

本章要点回顾

知识点一句话结论
传输层定位从主机到主机细化为进程到进程,靠端口号复用分用
套接字IP 地址 + 端口号,唯一确定一个通信端点
常用端口21 FTP、22 SSH、23 Telnet、25 SMTP、53 DNS、80 HTTP、443 HTTPS
UDP无连接不可靠,首部 8 字节,低延迟保边界
TCP 首部序号按字节编,窗口字段承载流量控制,SYN/ACK/FIN/RST
三次握手双方各交换并确认起始序号,第二三步防旧请求作祟
快重传快恢复三个重复确认即重传;超时归零重来,快重传减半继续
四次挥手双向独立关闭,ACK 与 FIN 之间可能还有数据要发
TIME_WAIT等 2MSL:保最后 ACK 送达 + 让旧报文死透
可靠四机制序号、确认、超时重传、滑动窗口
流量 vs 拥塞流量控制护接收方,拥塞控制护网络;取两窗口较小者
AIMD慢启动指数涨、拥塞避免线性涨、丢包乘性砍
连接四元组源 IP、源端口、目的 IP、目的端口共同唯一确定一条连接

做题提醒

  1. 握手三次、挥手四次,别记反;第二次握手是 SYN 与 ACK 合并的一个报文,不是两个。
  2. 三次握手的核心理由是"防止失效的旧连接请求突然到达服务器造成资源浪费",答题围绕这一点展开。
  3. 流量控制与拥塞控制的区别是高频简答与选择考点:前者防接收方溢出(接收窗口),后者防网络拥塞(拥塞窗口),对象不同、机制不同。
  4. TCP 面向字节流、不保留报文边界;UDP 面向数据报、保留边界——"TCP 保留应用报文边界"是错误说法。
  5. "UDP 不提供可靠传输所以毫无用处/实时业务只能用 UDP"这类绝对化选项一律存疑,DNS、QUIC 都是现成反例。
  6. TIME_WAIT 出现在主动关闭的一方,持续 2MSL;问"服务器/被动方进入 TIME_WAIT"的表述要小心主客体。
  7. 端口号 16 位、范围 0~65535,0~1023 为知名端口;"端口号是 32 位"混淆了 IP 地址的长度。
  8. "收到三个重复确认"触发的是快重传(窗口减半进入拥塞避免),"超时"才回到慢启动重新开始,两种丢包信号的处理力度不同。
  9. TCP 的序号对"字节"编号而非对"报文段"编号;确认号表示"期望收到的下一个字节",不是"已收到的最后一个字节"。