1. 引言
TCP(Transmission Control Protocol,传输控制协议)是互联网协议栈中最重要的传输层协议之一。它位于 IP 层之上,为应用层提供可靠、面向连接、基于字节流的通信服务。无论是浏览网页、发送邮件、传输文件,还是视频通话,绝大多数应用都依赖 TCP 来保证数据能够完整、有序地到达对端。
本文将从 TCP 的报文段结构出发,系统讲解连接管理(三次握手与四次挥手)、可靠传输机制、流量控制与拥塞控制等核心原理,帮助读者建立对 TCP 的整体认知。
2. TCP 报文段结构
在深入原理之前,先了解 TCP 报文段的基本格式。TCP 报文段由首部 和数据两部分组成,首部默认长度为 20 字节(不含选项字段)。
| 字段 | 长度 | 说明 |
|---|---|---|
| 源端口 / 目的端口 | 各 2 字节 | 标识通信的进程 |
| 序号(Sequence Number) | 4 字节 | 本报文段数据首字节的序号 |
| 确认号(Acknowledgment Number) | 4 字节 | 期望收到对方下一个字节的序号 |
| 数据偏移 | 4 位 | 首部长度 |
| 保留 | 6 位 | 保留未用 |
| 标志位 | 6 位 | URG、ACK、PSH、RST、SYN、FIN |
| 窗口(Window) | 2 字节 | 接收方的接收窗口大小 |
| 校验和 | 2 字节 | 校验首部与数据 |
| 紧急指针 | 2 字节 | 仅 URG 置位时有效 |
其中,六个标志位是理解 TCP 状态机的关键:
- SYN:同步序号,用于建立连接。
- ACK:确认序号有效。
- FIN:释放连接。
- RST:重置连接。
- PSH:立即交付应用层。
- URG:紧急数据。
3. 连接管理:三次握手与四次挥手
3.1 三次握手建立连接
TCP 建立连接需要经过三次报文交换,称为三次握手。其目的是确认双方的收发能力都正常,并同步初始序号。
服务端 客户端 服务端 客户端 #mermaid-svg-hdqE4qjulT8mSNL7{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-hdqE4qjulT8mSNL7 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-hdqE4qjulT8mSNL7 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-hdqE4qjulT8mSNL7 .error-icon{fill:#552222;}#mermaid-svg-hdqE4qjulT8mSNL7 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-hdqE4qjulT8mSNL7 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-hdqE4qjulT8mSNL7 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-hdqE4qjulT8mSNL7 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-hdqE4qjulT8mSNL7 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-hdqE4qjulT8mSNL7 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-hdqE4qjulT8mSNL7 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-hdqE4qjulT8mSNL7 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-hdqE4qjulT8mSNL7 .marker.cross{stroke:#333333;}#mermaid-svg-hdqE4qjulT8mSNL7 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-hdqE4qjulT8mSNL7 p{margin:0;}#mermaid-svg-hdqE4qjulT8mSNL7 .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-hdqE4qjulT8mSNL7 text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-hdqE4qjulT8mSNL7 .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-hdqE4qjulT8mSNL7 .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-hdqE4qjulT8mSNL7 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-hdqE4qjulT8mSNL7 .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-hdqE4qjulT8mSNL7 #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-hdqE4qjulT8mSNL7 .sequenceNumber{fill:white;}#mermaid-svg-hdqE4qjulT8mSNL7 #sequencenumber{fill:#333;}#mermaid-svg-hdqE4qjulT8mSNL7 #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-hdqE4qjulT8mSNL7 .messageText{fill:#333;stroke:none;}#mermaid-svg-hdqE4qjulT8mSNL7 .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-hdqE4qjulT8mSNL7 .labelText,#mermaid-svg-hdqE4qjulT8mSNL7 .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-hdqE4qjulT8mSNL7 .loopText,#mermaid-svg-hdqE4qjulT8mSNL7 .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-hdqE4qjulT8mSNL7 .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-hdqE4qjulT8mSNL7 .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-hdqE4qjulT8mSNL7 .noteText,#mermaid-svg-hdqE4qjulT8mSNL7 .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-hdqE4qjulT8mSNL7 .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-hdqE4qjulT8mSNL7 .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-hdqE4qjulT8mSNL7 .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-hdqE4qjulT8mSNL7 .actorPopupMenu{position:absolute;}#mermaid-svg-hdqE4qjulT8mSNL7 .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-hdqE4qjulT8mSNL7 .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-hdqE4qjulT8mSNL7 .actor-man circle,#mermaid-svg-hdqE4qjulT8mSNL7 line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-hdqE4qjulT8mSNL7 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} SYN=1, seq=x(SYN_SENT)SYN=1, ACK=1, seq=y, ack=x+1(SYN_RCVD)ACK=1, seq=x+1, ack=y+1(ESTABLISHED)
具体过程如下:
- 第一次握手 :客户端发送 SYN 报文,初始序号为
x,进入SYN_SENT状态。 - 第二次握手 :服务端收到后,回复 SYN+ACK 报文,自己的序号为
y,确认号为x+1,进入SYN_RCVD状态。 - 第三次握手 :客户端收到后,发送 ACK 报文,确认号为
y+1,双方进入ESTABLISHED状态。
为什么需要三次握手? 主要是为了防止已失效的连接请求突然又传到服务端,导致服务端误开连接、浪费资源。三次握手能让双方确认彼此的序号同步,避免历史报文造成混乱。
3.2 四次挥手释放连接
TCP 连接是全双工的,因此释放连接需要四次挥手,双方各自关闭一个方向的数据传输。
被动关闭方 主动关闭方 被动关闭方 主动关闭方 #mermaid-svg-T55MPGm1CZ8ZqMbu{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-T55MPGm1CZ8ZqMbu .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-T55MPGm1CZ8ZqMbu .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-T55MPGm1CZ8ZqMbu .error-icon{fill:#552222;}#mermaid-svg-T55MPGm1CZ8ZqMbu .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-T55MPGm1CZ8ZqMbu .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-T55MPGm1CZ8ZqMbu .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-T55MPGm1CZ8ZqMbu .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-T55MPGm1CZ8ZqMbu .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-T55MPGm1CZ8ZqMbu .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-T55MPGm1CZ8ZqMbu .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-T55MPGm1CZ8ZqMbu .marker{fill:#333333;stroke:#333333;}#mermaid-svg-T55MPGm1CZ8ZqMbu .marker.cross{stroke:#333333;}#mermaid-svg-T55MPGm1CZ8ZqMbu svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-T55MPGm1CZ8ZqMbu p{margin:0;}#mermaid-svg-T55MPGm1CZ8ZqMbu .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-T55MPGm1CZ8ZqMbu text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-T55MPGm1CZ8ZqMbu .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-T55MPGm1CZ8ZqMbu .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-T55MPGm1CZ8ZqMbu .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-T55MPGm1CZ8ZqMbu .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-T55MPGm1CZ8ZqMbu #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-T55MPGm1CZ8ZqMbu .sequenceNumber{fill:white;}#mermaid-svg-T55MPGm1CZ8ZqMbu #sequencenumber{fill:#333;}#mermaid-svg-T55MPGm1CZ8ZqMbu #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-T55MPGm1CZ8ZqMbu .messageText{fill:#333;stroke:none;}#mermaid-svg-T55MPGm1CZ8ZqMbu .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-T55MPGm1CZ8ZqMbu .labelText,#mermaid-svg-T55MPGm1CZ8ZqMbu .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-T55MPGm1CZ8ZqMbu .loopText,#mermaid-svg-T55MPGm1CZ8ZqMbu .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-T55MPGm1CZ8ZqMbu .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-T55MPGm1CZ8ZqMbu .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-T55MPGm1CZ8ZqMbu .noteText,#mermaid-svg-T55MPGm1CZ8ZqMbu .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-T55MPGm1CZ8ZqMbu .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-T55MPGm1CZ8ZqMbu .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-T55MPGm1CZ8ZqMbu .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-T55MPGm1CZ8ZqMbu .actorPopupMenu{position:absolute;}#mermaid-svg-T55MPGm1CZ8ZqMbu .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-T55MPGm1CZ8ZqMbu .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-T55MPGm1CZ8ZqMbu .actor-man circle,#mermaid-svg-T55MPGm1CZ8ZqMbu line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-T55MPGm1CZ8ZqMbu :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} FIN=1, seq=u(FIN_WAIT_1)ACK=1, ack=u+1(CLOSE_WAIT)FIN=1, seq=v(LAST_ACK)ACK=1, ack=v+1(TIME_WAIT)
- 第一次挥手 :主动方发送 FIN 报文,表示不再发送数据,进入
FIN_WAIT_1。 - 第二次挥手 :被动方回复 ACK,进入
CLOSE_WAIT;主动方收到后进入FIN_WAIT_2。 - 第三次挥手 :被动方处理完数据后,发送 FIN 报文,进入
LAST_ACK。 - 第四次挥手 :主动方回复 ACK,进入
TIME_WAIT,等待 2MSL 后关闭。
为什么需要 TIME_WAIT? 一是确保最后一个 ACK 能到达对端(若丢失可重传);二是让旧连接的报文在网络中自然消失,避免干扰新连接。
4. 可靠传输机制
TCP 的可靠性建立在序号、确认、重传三大机制之上。
4.1 序号与确认
TCP 将数据视为字节流,每个字节都有唯一的序号。发送方按序号发送数据,接收方收到后返回确认号,表示「该序号之前的数据都已正确收到」。
4.2 超时重传
发送方为每个已发送但未确认的报文启动定时器。若超时仍未收到 ACK,则重传该报文。超时时间(RTO)根据往返时间(RTT)动态计算,避免固定值导致效率低下。
4.3 快速重传
当接收方收到失序报文时,会立即重复发送对最后一个有序字节的 ACK。发送方连续收到 3 个重复 ACK 时,不等超时即重传丢失的报文,从而加快恢复速度。
4.4 选择性确认(SACK)
SACK 选项允许接收方告知发送方「哪些区间已收到」,发送方只需重传真正丢失的报文段,避免不必要的重传,提升带宽利用率。
5. 流量控制
流量控制的目的是防止发送方发送过快,导致接收方缓冲区溢出 。TCP 通过滑动窗口机制实现。
接收方在每次 ACK 中携带自己的接收窗口(rwnd) ,告知发送方「我还能接收多少字节」。发送方的发送窗口取 min(拥塞窗口 cwnd, 接收窗口 rwnd)。
#mermaid-svg-3k1QLkOkALCpHrc9{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-3k1QLkOkALCpHrc9 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-3k1QLkOkALCpHrc9 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-3k1QLkOkALCpHrc9 .error-icon{fill:#552222;}#mermaid-svg-3k1QLkOkALCpHrc9 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-3k1QLkOkALCpHrc9 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-3k1QLkOkALCpHrc9 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-3k1QLkOkALCpHrc9 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-3k1QLkOkALCpHrc9 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-3k1QLkOkALCpHrc9 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-3k1QLkOkALCpHrc9 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-3k1QLkOkALCpHrc9 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-3k1QLkOkALCpHrc9 .marker.cross{stroke:#333333;}#mermaid-svg-3k1QLkOkALCpHrc9 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-3k1QLkOkALCpHrc9 p{margin:0;}#mermaid-svg-3k1QLkOkALCpHrc9 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-3k1QLkOkALCpHrc9 .cluster-label text{fill:#333;}#mermaid-svg-3k1QLkOkALCpHrc9 .cluster-label span{color:#333;}#mermaid-svg-3k1QLkOkALCpHrc9 .cluster-label span p{background-color:transparent;}#mermaid-svg-3k1QLkOkALCpHrc9 .label text,#mermaid-svg-3k1QLkOkALCpHrc9 span{fill:#333;color:#333;}#mermaid-svg-3k1QLkOkALCpHrc9 .node rect,#mermaid-svg-3k1QLkOkALCpHrc9 .node circle,#mermaid-svg-3k1QLkOkALCpHrc9 .node ellipse,#mermaid-svg-3k1QLkOkALCpHrc9 .node polygon,#mermaid-svg-3k1QLkOkALCpHrc9 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-3k1QLkOkALCpHrc9 .rough-node .label text,#mermaid-svg-3k1QLkOkALCpHrc9 .node .label text,#mermaid-svg-3k1QLkOkALCpHrc9 .image-shape .label,#mermaid-svg-3k1QLkOkALCpHrc9 .icon-shape .label{text-anchor:middle;}#mermaid-svg-3k1QLkOkALCpHrc9 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-3k1QLkOkALCpHrc9 .rough-node .label,#mermaid-svg-3k1QLkOkALCpHrc9 .node .label,#mermaid-svg-3k1QLkOkALCpHrc9 .image-shape .label,#mermaid-svg-3k1QLkOkALCpHrc9 .icon-shape .label{text-align:center;}#mermaid-svg-3k1QLkOkALCpHrc9 .node.clickable{cursor:pointer;}#mermaid-svg-3k1QLkOkALCpHrc9 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-3k1QLkOkALCpHrc9 .arrowheadPath{fill:#333333;}#mermaid-svg-3k1QLkOkALCpHrc9 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-3k1QLkOkALCpHrc9 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-3k1QLkOkALCpHrc9 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-3k1QLkOkALCpHrc9 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-3k1QLkOkALCpHrc9 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-3k1QLkOkALCpHrc9 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-3k1QLkOkALCpHrc9 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-3k1QLkOkALCpHrc9 .cluster text{fill:#333;}#mermaid-svg-3k1QLkOkALCpHrc9 .cluster span{color:#333;}#mermaid-svg-3k1QLkOkALCpHrc9 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-3k1QLkOkALCpHrc9 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-3k1QLkOkALCpHrc9 rect.text{fill:none;stroke-width:0;}#mermaid-svg-3k1QLkOkALCpHrc9 .icon-shape,#mermaid-svg-3k1QLkOkALCpHrc9 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-3k1QLkOkALCpHrc9 .icon-shape p,#mermaid-svg-3k1QLkOkALCpHrc9 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-3k1QLkOkALCpHrc9 .icon-shape .label rect,#mermaid-svg-3k1QLkOkALCpHrc9 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-3k1QLkOkALCpHrc9 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-3k1QLkOkALCpHrc9 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-3k1QLkOkALCpHrc9 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 发送窗口 = min(cwnd, rwnd)
ACK + rwnd
发送方
接收方
一个典型问题是窗口零通告 :当接收方缓冲区满时,rwnd 变为 0,发送方停止发送。为防止死锁,发送方会定期发送 1 字节的探测报文,询问接收方窗口是否恢复。
6. 拥塞控制
拥塞控制是全局性的,目的是避免过多数据注入网络导致路由器拥塞。TCP 采用四种算法配合工作。
6.1 慢启动
连接建立后,拥塞窗口 cwnd 从 1 个 MSS 开始,每收到一个 ACK 就加 1,呈指数增长 。当 cwnd 达到慢启动阈值 ssthresh 时,转入拥塞避免。
6.2 拥塞避免
cwnd 每经过一个 RTT 只增加 1 个 MSS,呈线性增长,增长较为平缓。
6.3 快重传与快恢复
当发送方收到 3 个重复 ACK 时:
- 将
ssthresh减半; cwnd设为ssthresh,进入快恢复;- 之后按拥塞避免的线性方式增长。
若发生超时,则 ssthresh 减半,cwnd 重置为 1,重新进入慢启动。
#mermaid-svg-p3cosR286FmvqlKm{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-p3cosR286FmvqlKm .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-p3cosR286FmvqlKm .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-p3cosR286FmvqlKm .error-icon{fill:#552222;}#mermaid-svg-p3cosR286FmvqlKm .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-p3cosR286FmvqlKm .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-p3cosR286FmvqlKm .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-p3cosR286FmvqlKm .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-p3cosR286FmvqlKm .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-p3cosR286FmvqlKm .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-p3cosR286FmvqlKm .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-p3cosR286FmvqlKm .marker{fill:#333333;stroke:#333333;}#mermaid-svg-p3cosR286FmvqlKm .marker.cross{stroke:#333333;}#mermaid-svg-p3cosR286FmvqlKm svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-p3cosR286FmvqlKm p{margin:0;}#mermaid-svg-p3cosR286FmvqlKm .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-p3cosR286FmvqlKm .cluster-label text{fill:#333;}#mermaid-svg-p3cosR286FmvqlKm .cluster-label span{color:#333;}#mermaid-svg-p3cosR286FmvqlKm .cluster-label span p{background-color:transparent;}#mermaid-svg-p3cosR286FmvqlKm .label text,#mermaid-svg-p3cosR286FmvqlKm span{fill:#333;color:#333;}#mermaid-svg-p3cosR286FmvqlKm .node rect,#mermaid-svg-p3cosR286FmvqlKm .node circle,#mermaid-svg-p3cosR286FmvqlKm .node ellipse,#mermaid-svg-p3cosR286FmvqlKm .node polygon,#mermaid-svg-p3cosR286FmvqlKm .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-p3cosR286FmvqlKm .rough-node .label text,#mermaid-svg-p3cosR286FmvqlKm .node .label text,#mermaid-svg-p3cosR286FmvqlKm .image-shape .label,#mermaid-svg-p3cosR286FmvqlKm .icon-shape .label{text-anchor:middle;}#mermaid-svg-p3cosR286FmvqlKm .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-p3cosR286FmvqlKm .rough-node .label,#mermaid-svg-p3cosR286FmvqlKm .node .label,#mermaid-svg-p3cosR286FmvqlKm .image-shape .label,#mermaid-svg-p3cosR286FmvqlKm .icon-shape .label{text-align:center;}#mermaid-svg-p3cosR286FmvqlKm .node.clickable{cursor:pointer;}#mermaid-svg-p3cosR286FmvqlKm .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-p3cosR286FmvqlKm .arrowheadPath{fill:#333333;}#mermaid-svg-p3cosR286FmvqlKm .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-p3cosR286FmvqlKm .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-p3cosR286FmvqlKm .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-p3cosR286FmvqlKm .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-p3cosR286FmvqlKm .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-p3cosR286FmvqlKm .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-p3cosR286FmvqlKm .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-p3cosR286FmvqlKm .cluster text{fill:#333;}#mermaid-svg-p3cosR286FmvqlKm .cluster span{color:#333;}#mermaid-svg-p3cosR286FmvqlKm div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-p3cosR286FmvqlKm .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-p3cosR286FmvqlKm rect.text{fill:none;stroke-width:0;}#mermaid-svg-p3cosR286FmvqlKm .icon-shape,#mermaid-svg-p3cosR286FmvqlKm .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-p3cosR286FmvqlKm .icon-shape p,#mermaid-svg-p3cosR286FmvqlKm .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-p3cosR286FmvqlKm .icon-shape .label rect,#mermaid-svg-p3cosR286FmvqlKm .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-p3cosR286FmvqlKm .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-p3cosR286FmvqlKm .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-p3cosR286FmvqlKm :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} cwnd >= ssthresh
3 个重复 ACK
超时
慢启动
cwnd 指数增长
拥塞避免
cwnd 线性增长
快重传 + 快恢复
7. 常见问题与优化
- Nagle 算法:合并小报文减少网络开销,但可能增加延迟,实时应用可关闭。
- 延迟确认:接收方延迟一段时间再合并确认,减少 ACK 数量。
- TCP_NODELAY:在 socket 层面关闭 Nagle 算法,降低交互式应用的延迟。
- Keep-Alive:定期发送探测报文,检测对端是否存活。
8. 总结
TCP 通过三次握手 建立可靠连接,用序号、确认与重传 保证数据不丢不乱,用滑动窗口 实现流量控制,用慢启动、拥塞避免、快重传与快恢复应对网络拥塞。理解这些核心机制,是排查网络问题、优化应用性能的基础。
希望本文能帮助你建立起对 TCP 原理的系统认识。如果你对某个机制想深入了解,欢迎在评论区留言讨论。