网络基础系列
上一篇我们拆了ping:它主要靠ICMP做网络层探测。今天开始进入传输层,讲两个最常见、也最容易被拿来对比的协议:TCP和UDP。
一、开场:为什么有了TCP,还要UDP?
很多人第一次学TCP和UDP,都记住一句话:
TCP可靠,UDP不可靠。
这句话没错,但太短了,短到容易让人误会。
于是很多人脑子里形成朴素判断:
text
TCP = 好学生,可靠稳重
UDP = 坏学生,丢三落四
然后自然就会问:既然TCP这么可靠,为什么还要UDP?
这个问题很合理。如果"可靠"永远是唯一目标,UDP确实像多余的。
但网络世界不只追求"可靠",它还追求:
| 目标 | 说明 |
|---|---|
| 低延迟 | 快比完整更重要 |
| 简单 | 协议栈开销小 |
| 少开销 | 头部小、状态少 |
| 可控性 | 应用自己决定策略 |
| 实时性 | 过期数据不如不要 |
更准确的说法:TCP把可靠性做在传输层里,UDP把控制权留给应用层。
通俗比喻:
| 协议 | 比喻 |
|---|---|
| TCP | 顺丰保价签收------流程多,但稳 |
| UDP | 现场喊话广播------不保证每个人都听到,但快 |
不同场景需要不同工具。不能用锤子拧螺丝------虽然现实中确实有人这么干,通常会留下事故报告。
二、一张图看懂TCP和UDP的位置
TCP和UDP都属于传输层,运行在IP之上。
text
应用层:HTTP / DNS / QUIC / 自定义协议
传输层:TCP / UDP
网络层:IP
链路层:以太网 / Wi-Fi
#mermaid-svg-aFI7zgiflvZr9VMr{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-aFI7zgiflvZr9VMr .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-aFI7zgiflvZr9VMr .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-aFI7zgiflvZr9VMr .error-icon{fill:#552222;}#mermaid-svg-aFI7zgiflvZr9VMr .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-aFI7zgiflvZr9VMr .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-aFI7zgiflvZr9VMr .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-aFI7zgiflvZr9VMr .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-aFI7zgiflvZr9VMr .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-aFI7zgiflvZr9VMr .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-aFI7zgiflvZr9VMr .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-aFI7zgiflvZr9VMr .marker{fill:#333333;stroke:#333333;}#mermaid-svg-aFI7zgiflvZr9VMr .marker.cross{stroke:#333333;}#mermaid-svg-aFI7zgiflvZr9VMr svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-aFI7zgiflvZr9VMr p{margin:0;}#mermaid-svg-aFI7zgiflvZr9VMr .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-aFI7zgiflvZr9VMr .cluster-label text{fill:#333;}#mermaid-svg-aFI7zgiflvZr9VMr .cluster-label span{color:#333;}#mermaid-svg-aFI7zgiflvZr9VMr .cluster-label span p{background-color:transparent;}#mermaid-svg-aFI7zgiflvZr9VMr .label text,#mermaid-svg-aFI7zgiflvZr9VMr span{fill:#333;color:#333;}#mermaid-svg-aFI7zgiflvZr9VMr .node rect,#mermaid-svg-aFI7zgiflvZr9VMr .node circle,#mermaid-svg-aFI7zgiflvZr9VMr .node ellipse,#mermaid-svg-aFI7zgiflvZr9VMr .node polygon,#mermaid-svg-aFI7zgiflvZr9VMr .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-aFI7zgiflvZr9VMr .rough-node .label text,#mermaid-svg-aFI7zgiflvZr9VMr .node .label text,#mermaid-svg-aFI7zgiflvZr9VMr .image-shape .label,#mermaid-svg-aFI7zgiflvZr9VMr .icon-shape .label{text-anchor:middle;}#mermaid-svg-aFI7zgiflvZr9VMr .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-aFI7zgiflvZr9VMr .rough-node .label,#mermaid-svg-aFI7zgiflvZr9VMr .node .label,#mermaid-svg-aFI7zgiflvZr9VMr .image-shape .label,#mermaid-svg-aFI7zgiflvZr9VMr .icon-shape .label{text-align:center;}#mermaid-svg-aFI7zgiflvZr9VMr .node.clickable{cursor:pointer;}#mermaid-svg-aFI7zgiflvZr9VMr .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-aFI7zgiflvZr9VMr .arrowheadPath{fill:#333333;}#mermaid-svg-aFI7zgiflvZr9VMr .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-aFI7zgiflvZr9VMr .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-aFI7zgiflvZr9VMr .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-aFI7zgiflvZr9VMr .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-aFI7zgiflvZr9VMr .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-aFI7zgiflvZr9VMr .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-aFI7zgiflvZr9VMr .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-aFI7zgiflvZr9VMr .cluster text{fill:#333;}#mermaid-svg-aFI7zgiflvZr9VMr .cluster span{color:#333;}#mermaid-svg-aFI7zgiflvZr9VMr 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-aFI7zgiflvZr9VMr .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-aFI7zgiflvZr9VMr rect.text{fill:none;stroke-width:0;}#mermaid-svg-aFI7zgiflvZr9VMr .icon-shape,#mermaid-svg-aFI7zgiflvZr9VMr .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-aFI7zgiflvZr9VMr .icon-shape p,#mermaid-svg-aFI7zgiflvZr9VMr .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-aFI7zgiflvZr9VMr .icon-shape .label rect,#mermaid-svg-aFI7zgiflvZr9VMr .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-aFI7zgiflvZr9VMr .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-aFI7zgiflvZr9VMr .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-aFI7zgiflvZr9VMr :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 应用层协议
选择传输层协议
TCP
连接
可靠
有序
流式
UDP
无连接
尽力而为
消息式
低开销
IP
链路层发送
它们解决的核心问题:
主机上的一个进程,如何和另一台主机上的一个进程通信?
IP负责把包送到目标主机 ,传输层负责进一步区分------这台主机上的哪个应用进程(靠端口,下一篇细讲)。
一句话对比:
| 协议 | 核心特点 |
|---|---|
| TCP | 面向连接、可靠、有序、字节流 |
| UDP | 无连接、尽力而为、消息边界清晰、低开销 |
注意:不是说"TCP高级,UDP低级"。它们是不同取舍,没有好坏,只有适不适合。
三、TCP:先建立关系,再认真传输
TCP是面向连接 的协议。正式传数据前,通信双方要先建立连接------三次握手:
服务端 客户端 服务端 客户端 #mermaid-svg-LZeu6QzrVpTT2YA9{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-LZeu6QzrVpTT2YA9 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-LZeu6QzrVpTT2YA9 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-LZeu6QzrVpTT2YA9 .error-icon{fill:#552222;}#mermaid-svg-LZeu6QzrVpTT2YA9 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-LZeu6QzrVpTT2YA9 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-LZeu6QzrVpTT2YA9 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-LZeu6QzrVpTT2YA9 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-LZeu6QzrVpTT2YA9 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-LZeu6QzrVpTT2YA9 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-LZeu6QzrVpTT2YA9 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-LZeu6QzrVpTT2YA9 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-LZeu6QzrVpTT2YA9 .marker.cross{stroke:#333333;}#mermaid-svg-LZeu6QzrVpTT2YA9 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-LZeu6QzrVpTT2YA9 p{margin:0;}#mermaid-svg-LZeu6QzrVpTT2YA9 .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-LZeu6QzrVpTT2YA9 text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-LZeu6QzrVpTT2YA9 .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-LZeu6QzrVpTT2YA9 .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-LZeu6QzrVpTT2YA9 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-LZeu6QzrVpTT2YA9 .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-LZeu6QzrVpTT2YA9 #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-LZeu6QzrVpTT2YA9 .sequenceNumber{fill:white;}#mermaid-svg-LZeu6QzrVpTT2YA9 #sequencenumber{fill:#333;}#mermaid-svg-LZeu6QzrVpTT2YA9 #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-LZeu6QzrVpTT2YA9 .messageText{fill:#333;stroke:none;}#mermaid-svg-LZeu6QzrVpTT2YA9 .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-LZeu6QzrVpTT2YA9 .labelText,#mermaid-svg-LZeu6QzrVpTT2YA9 .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-LZeu6QzrVpTT2YA9 .loopText,#mermaid-svg-LZeu6QzrVpTT2YA9 .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-LZeu6QzrVpTT2YA9 .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-LZeu6QzrVpTT2YA9 .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-LZeu6QzrVpTT2YA9 .noteText,#mermaid-svg-LZeu6QzrVpTT2YA9 .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-LZeu6QzrVpTT2YA9 .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-LZeu6QzrVpTT2YA9 .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-LZeu6QzrVpTT2YA9 .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-LZeu6QzrVpTT2YA9 .actorPopupMenu{position:absolute;}#mermaid-svg-LZeu6QzrVpTT2YA9 .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-LZeu6QzrVpTT2YA9 .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-LZeu6QzrVpTT2YA9 .actor-man circle,#mermaid-svg-LZeu6QzrVpTT2YA9 line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-LZeu6QzrVpTT2YA9 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} SYN:我想建立连接SYN+ACK:可以,我也准备好了ACK:确认,开始通信发送数据确认收到
TCP追求的能力:
| 能力 | 作用 |
|---|---|
| 数据不丢 | 丢包能重传 |
| 乱序重排 | 到达顺序错乱时重新排序 |
| 重复去重 | 重复包自动丢弃 |
| 流量控制 | 接收方来不及时让发送方慢点 |
| 拥塞控制 | 网络拥塞时自动降速 |
这些能力让TCP很强,但也带来成本:需要维护连接状态、序列号、ACK、重传、拥塞控制、滑动窗口。
比喻:TCP像一个项目经理,每个需求都建看板、排期、验收、复盘------流程完整,但问一句"中午吃啥"也用这个流程,就太重了。
四、UDP:先发出去,其他你自己决定
UDP是无连接的协议。发送方不需要先建立连接,想发就发:
服务端 客户端 服务端 客户端 #mermaid-svg-xjGo5ajK8ekMaFC4{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-xjGo5ajK8ekMaFC4 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-xjGo5ajK8ekMaFC4 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-xjGo5ajK8ekMaFC4 .error-icon{fill:#552222;}#mermaid-svg-xjGo5ajK8ekMaFC4 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-xjGo5ajK8ekMaFC4 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-xjGo5ajK8ekMaFC4 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-xjGo5ajK8ekMaFC4 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-xjGo5ajK8ekMaFC4 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-xjGo5ajK8ekMaFC4 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-xjGo5ajK8ekMaFC4 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-xjGo5ajK8ekMaFC4 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-xjGo5ajK8ekMaFC4 .marker.cross{stroke:#333333;}#mermaid-svg-xjGo5ajK8ekMaFC4 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-xjGo5ajK8ekMaFC4 p{margin:0;}#mermaid-svg-xjGo5ajK8ekMaFC4 .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-xjGo5ajK8ekMaFC4 text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-xjGo5ajK8ekMaFC4 .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-xjGo5ajK8ekMaFC4 .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-xjGo5ajK8ekMaFC4 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-xjGo5ajK8ekMaFC4 .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-xjGo5ajK8ekMaFC4 #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-xjGo5ajK8ekMaFC4 .sequenceNumber{fill:white;}#mermaid-svg-xjGo5ajK8ekMaFC4 #sequencenumber{fill:#333;}#mermaid-svg-xjGo5ajK8ekMaFC4 #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-xjGo5ajK8ekMaFC4 .messageText{fill:#333;stroke:none;}#mermaid-svg-xjGo5ajK8ekMaFC4 .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-xjGo5ajK8ekMaFC4 .labelText,#mermaid-svg-xjGo5ajK8ekMaFC4 .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-xjGo5ajK8ekMaFC4 .loopText,#mermaid-svg-xjGo5ajK8ekMaFC4 .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-xjGo5ajK8ekMaFC4 .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-xjGo5ajK8ekMaFC4 .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-xjGo5ajK8ekMaFC4 .noteText,#mermaid-svg-xjGo5ajK8ekMaFC4 .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-xjGo5ajK8ekMaFC4 .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-xjGo5ajK8ekMaFC4 .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-xjGo5ajK8ekMaFC4 .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-xjGo5ajK8ekMaFC4 .actorPopupMenu{position:absolute;}#mermaid-svg-xjGo5ajK8ekMaFC4 .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-xjGo5ajK8ekMaFC4 .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-xjGo5ajK8ekMaFC4 .actor-man circle,#mermaid-svg-xjGo5ajK8ekMaFC4 line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-xjGo5ajK8ekMaFC4 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} UDP 数据报 1UDP 数据报 2UDP 数据报 3
UDP本身不保证:
- 一定送达
- 按顺序到达
- 不重复
- 对方接收
- 网络拥塞时自动降速
但它的优点也很明显:
| 优点 | 说明 |
|---|---|
| 头部更小 | 8字节 vs TCP的20字节+ |
| 无连接 | 不需要三次握手 |
| 延迟更低 | 没有握手、确认、重传等待 |
| 无队头阻塞 | 一个包丢了不影响后续包 |
| 应用可控 | 应用自己设计可靠性策略 |
比喻:UDP像说"我只负责把数据报交给IP,剩下你应用自己看着办"------不是不负责任,是边界清晰。
为什么实时场景不想要TCP的重传:实时语音丢了一小段,可能还能继续听。但如果为了重传那一小段导致后面的声音都卡住,体验更差。过期的数据有时比丢失的数据更没价值。
五、头部对比:8字节 vs 20字节
UDP头部:仅8字节
text
┌───────────────┬───────────────┐
│ 源端口 │ 目标端口 │
├───────────────┼───────────────┤
│ 长度 │ 校验和 │
└───────────────┴───────────────┘
TCP头部:最少20字节,还可能有选项
text
┌───────────────┬───────────────┐
│ 源端口 │ 目标端口 │
├───────────────┴───────────────┤
│ 序列号 │
├───────────────────────────────┤
│ 确认号 │
├───────────┬───────┬───────────┤
│ 头部长度 │ 标志位 │ 窗口大小 │
├───────────┴───────┴───────────┤
│ 校验和 / 紧急指针 / 选项 │
└───────────────────────────────┘
对比表格:
| 对比项 | TCP | UDP |
|---|---|---|
| 最小头部 | 20字节 | 8字节 |
| 序列号 | 有 | 无 |
| 确认号 | 有 | 无 |
| 窗口 | 有 | 无 |
| 连接状态 | 有 | 无 |
| 消息边界 | 不保留(字节流) | 保留(数据报) |
TCP头部复杂因为要做更多事,UDP简单因为做得少。不是谁更先进,是职责不同。
六、可靠性:TCP到底可靠在哪里?
TCP的可靠不是魔法,是一组机制的组合:
#mermaid-svg-sftrB57K42RVnPnr{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-sftrB57K42RVnPnr .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-sftrB57K42RVnPnr .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-sftrB57K42RVnPnr .error-icon{fill:#552222;}#mermaid-svg-sftrB57K42RVnPnr .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-sftrB57K42RVnPnr .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-sftrB57K42RVnPnr .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-sftrB57K42RVnPnr .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-sftrB57K42RVnPnr .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-sftrB57K42RVnPnr .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-sftrB57K42RVnPnr .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-sftrB57K42RVnPnr .marker{fill:#333333;stroke:#333333;}#mermaid-svg-sftrB57K42RVnPnr .marker.cross{stroke:#333333;}#mermaid-svg-sftrB57K42RVnPnr svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-sftrB57K42RVnPnr p{margin:0;}#mermaid-svg-sftrB57K42RVnPnr .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-sftrB57K42RVnPnr .cluster-label text{fill:#333;}#mermaid-svg-sftrB57K42RVnPnr .cluster-label span{color:#333;}#mermaid-svg-sftrB57K42RVnPnr .cluster-label span p{background-color:transparent;}#mermaid-svg-sftrB57K42RVnPnr .label text,#mermaid-svg-sftrB57K42RVnPnr span{fill:#333;color:#333;}#mermaid-svg-sftrB57K42RVnPnr .node rect,#mermaid-svg-sftrB57K42RVnPnr .node circle,#mermaid-svg-sftrB57K42RVnPnr .node ellipse,#mermaid-svg-sftrB57K42RVnPnr .node polygon,#mermaid-svg-sftrB57K42RVnPnr .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-sftrB57K42RVnPnr .rough-node .label text,#mermaid-svg-sftrB57K42RVnPnr .node .label text,#mermaid-svg-sftrB57K42RVnPnr .image-shape .label,#mermaid-svg-sftrB57K42RVnPnr .icon-shape .label{text-anchor:middle;}#mermaid-svg-sftrB57K42RVnPnr .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-sftrB57K42RVnPnr .rough-node .label,#mermaid-svg-sftrB57K42RVnPnr .node .label,#mermaid-svg-sftrB57K42RVnPnr .image-shape .label,#mermaid-svg-sftrB57K42RVnPnr .icon-shape .label{text-align:center;}#mermaid-svg-sftrB57K42RVnPnr .node.clickable{cursor:pointer;}#mermaid-svg-sftrB57K42RVnPnr .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-sftrB57K42RVnPnr .arrowheadPath{fill:#333333;}#mermaid-svg-sftrB57K42RVnPnr .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-sftrB57K42RVnPnr .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-sftrB57K42RVnPnr .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-sftrB57K42RVnPnr .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-sftrB57K42RVnPnr .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-sftrB57K42RVnPnr .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-sftrB57K42RVnPnr .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-sftrB57K42RVnPnr .cluster text{fill:#333;}#mermaid-svg-sftrB57K42RVnPnr .cluster span{color:#333;}#mermaid-svg-sftrB57K42RVnPnr 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-sftrB57K42RVnPnr .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-sftrB57K42RVnPnr rect.text{fill:none;stroke-width:0;}#mermaid-svg-sftrB57K42RVnPnr .icon-shape,#mermaid-svg-sftrB57K42RVnPnr .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-sftrB57K42RVnPnr .icon-shape p,#mermaid-svg-sftrB57K42RVnPnr .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-sftrB57K42RVnPnr .icon-shape .label rect,#mermaid-svg-sftrB57K42RVnPnr .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-sftrB57K42RVnPnr .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-sftrB57K42RVnPnr .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-sftrB57K42RVnPnr :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} TCP可靠性
序列号
ACK确认
超时/快速重传
乱序重排
流量控制
拥塞控制
| 机制 | 作用 |
|---|---|
| 序列号 | 给字节流编号,接收方可知道哪些到了、哪些没到、是否乱序、是否重复 |
| ACK确认 | 接收方返回确认,告诉发送方"我已收到哪一部分" |
| 重传 | 发送方发现某段数据迟迟没被确认,就重传 |
| 有序交付 | IP包乱序到达时,TCP在接收端重排序后再交给应用 |
| 流量控制 | 接收方通过窗口告诉发送方"我还能接多少" |
| 拥塞控制 | TCP根据网络状况调整发送速度,避免打爆网络 |
可靠不是免费的------它用延迟、状态、复杂度和带宽开销换来。工程世界没有白嫖,账单有时藏在性能指标里。
七、UDP真的"不可靠"吗?
说UDP不可靠,是指:UDP协议本身不提供TCP那些可靠传输机制。
但这不代表使用UDP的应用就一定不可靠。应用可以在UDP之上自己实现:
- 序列号
- ACK
- 重传
- 拥塞控制
- 加密
- 多路复用
- 丢包恢复
典型例子:QUIC
QUIC运行在UDP之上,但在应用/传输逻辑里实现了可靠传输、安全握手、多路复用等能力。HTTP/3就基于QUIC。
#mermaid-svg-AdlcYdCtRWj4RM49{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-AdlcYdCtRWj4RM49 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-AdlcYdCtRWj4RM49 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-AdlcYdCtRWj4RM49 .error-icon{fill:#552222;}#mermaid-svg-AdlcYdCtRWj4RM49 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-AdlcYdCtRWj4RM49 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-AdlcYdCtRWj4RM49 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-AdlcYdCtRWj4RM49 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-AdlcYdCtRWj4RM49 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-AdlcYdCtRWj4RM49 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-AdlcYdCtRWj4RM49 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-AdlcYdCtRWj4RM49 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-AdlcYdCtRWj4RM49 .marker.cross{stroke:#333333;}#mermaid-svg-AdlcYdCtRWj4RM49 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-AdlcYdCtRWj4RM49 p{margin:0;}#mermaid-svg-AdlcYdCtRWj4RM49 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-AdlcYdCtRWj4RM49 .cluster-label text{fill:#333;}#mermaid-svg-AdlcYdCtRWj4RM49 .cluster-label span{color:#333;}#mermaid-svg-AdlcYdCtRWj4RM49 .cluster-label span p{background-color:transparent;}#mermaid-svg-AdlcYdCtRWj4RM49 .label text,#mermaid-svg-AdlcYdCtRWj4RM49 span{fill:#333;color:#333;}#mermaid-svg-AdlcYdCtRWj4RM49 .node rect,#mermaid-svg-AdlcYdCtRWj4RM49 .node circle,#mermaid-svg-AdlcYdCtRWj4RM49 .node ellipse,#mermaid-svg-AdlcYdCtRWj4RM49 .node polygon,#mermaid-svg-AdlcYdCtRWj4RM49 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-AdlcYdCtRWj4RM49 .rough-node .label text,#mermaid-svg-AdlcYdCtRWj4RM49 .node .label text,#mermaid-svg-AdlcYdCtRWj4RM49 .image-shape .label,#mermaid-svg-AdlcYdCtRWj4RM49 .icon-shape .label{text-anchor:middle;}#mermaid-svg-AdlcYdCtRWj4RM49 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-AdlcYdCtRWj4RM49 .rough-node .label,#mermaid-svg-AdlcYdCtRWj4RM49 .node .label,#mermaid-svg-AdlcYdCtRWj4RM49 .image-shape .label,#mermaid-svg-AdlcYdCtRWj4RM49 .icon-shape .label{text-align:center;}#mermaid-svg-AdlcYdCtRWj4RM49 .node.clickable{cursor:pointer;}#mermaid-svg-AdlcYdCtRWj4RM49 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-AdlcYdCtRWj4RM49 .arrowheadPath{fill:#333333;}#mermaid-svg-AdlcYdCtRWj4RM49 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-AdlcYdCtRWj4RM49 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-AdlcYdCtRWj4RM49 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-AdlcYdCtRWj4RM49 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-AdlcYdCtRWj4RM49 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-AdlcYdCtRWj4RM49 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-AdlcYdCtRWj4RM49 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-AdlcYdCtRWj4RM49 .cluster text{fill:#333;}#mermaid-svg-AdlcYdCtRWj4RM49 .cluster span{color:#333;}#mermaid-svg-AdlcYdCtRWj4RM49 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-AdlcYdCtRWj4RM49 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-AdlcYdCtRWj4RM49 rect.text{fill:none;stroke-width:0;}#mermaid-svg-AdlcYdCtRWj4RM49 .icon-shape,#mermaid-svg-AdlcYdCtRWj4RM49 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-AdlcYdCtRWj4RM49 .icon-shape p,#mermaid-svg-AdlcYdCtRWj4RM49 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-AdlcYdCtRWj4RM49 .icon-shape .label rect,#mermaid-svg-AdlcYdCtRWj4RM49 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-AdlcYdCtRWj4RM49 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-AdlcYdCtRWj4RM49 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-AdlcYdCtRWj4RM49 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 应用
QUIC
UDP
IP
可靠传输
加密
拥塞控制
多路复用
准确说法:UDP本身不保证可靠,但应用可以基于UDP自己设计可靠性。
比喻:UDP像毛坯房------开发商没精装修,但你可以自己装成豪宅(当然也可能装成事故现场,看工程能力)。
八、字节流 vs 数据报:最容易被忽视的区别
这是TCP和UDP最核心的区别之一。
TCP是字节流
应用写入TCP的数据,在对端读取时不一定保持原来的"消息边界"。
示例:发送方写两次
text
write("hello")
write("world")
接收方可能一次读到:
text
helloworld
也可能分多次读到:
text
he
llow
orld
TCP只保证字节顺序,不保证应用层的消息边界。所以应用协议要自己设计分包方式:
- 固定长度
- 分隔符(如
\r\n) - 长度字段(如HTTP的Content-Length)
UDP是数据报
UDP一次send对应一个数据报,接收时以数据报为单位,消息边界天然存在。
#mermaid-svg-KUvGQa2rMEn5K3jm{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-KUvGQa2rMEn5K3jm .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-KUvGQa2rMEn5K3jm .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-KUvGQa2rMEn5K3jm .error-icon{fill:#552222;}#mermaid-svg-KUvGQa2rMEn5K3jm .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-KUvGQa2rMEn5K3jm .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-KUvGQa2rMEn5K3jm .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-KUvGQa2rMEn5K3jm .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-KUvGQa2rMEn5K3jm .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-KUvGQa2rMEn5K3jm .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-KUvGQa2rMEn5K3jm .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-KUvGQa2rMEn5K3jm .marker{fill:#333333;stroke:#333333;}#mermaid-svg-KUvGQa2rMEn5K3jm .marker.cross{stroke:#333333;}#mermaid-svg-KUvGQa2rMEn5K3jm svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-KUvGQa2rMEn5K3jm p{margin:0;}#mermaid-svg-KUvGQa2rMEn5K3jm .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-KUvGQa2rMEn5K3jm .cluster-label text{fill:#333;}#mermaid-svg-KUvGQa2rMEn5K3jm .cluster-label span{color:#333;}#mermaid-svg-KUvGQa2rMEn5K3jm .cluster-label span p{background-color:transparent;}#mermaid-svg-KUvGQa2rMEn5K3jm .label text,#mermaid-svg-KUvGQa2rMEn5K3jm span{fill:#333;color:#333;}#mermaid-svg-KUvGQa2rMEn5K3jm .node rect,#mermaid-svg-KUvGQa2rMEn5K3jm .node circle,#mermaid-svg-KUvGQa2rMEn5K3jm .node ellipse,#mermaid-svg-KUvGQa2rMEn5K3jm .node polygon,#mermaid-svg-KUvGQa2rMEn5K3jm .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-KUvGQa2rMEn5K3jm .rough-node .label text,#mermaid-svg-KUvGQa2rMEn5K3jm .node .label text,#mermaid-svg-KUvGQa2rMEn5K3jm .image-shape .label,#mermaid-svg-KUvGQa2rMEn5K3jm .icon-shape .label{text-anchor:middle;}#mermaid-svg-KUvGQa2rMEn5K3jm .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-KUvGQa2rMEn5K3jm .rough-node .label,#mermaid-svg-KUvGQa2rMEn5K3jm .node .label,#mermaid-svg-KUvGQa2rMEn5K3jm .image-shape .label,#mermaid-svg-KUvGQa2rMEn5K3jm .icon-shape .label{text-align:center;}#mermaid-svg-KUvGQa2rMEn5K3jm .node.clickable{cursor:pointer;}#mermaid-svg-KUvGQa2rMEn5K3jm .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-KUvGQa2rMEn5K3jm .arrowheadPath{fill:#333333;}#mermaid-svg-KUvGQa2rMEn5K3jm .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-KUvGQa2rMEn5K3jm .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-KUvGQa2rMEn5K3jm .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-KUvGQa2rMEn5K3jm .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-KUvGQa2rMEn5K3jm .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-KUvGQa2rMEn5K3jm .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-KUvGQa2rMEn5K3jm .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-KUvGQa2rMEn5K3jm .cluster text{fill:#333;}#mermaid-svg-KUvGQa2rMEn5K3jm .cluster span{color:#333;}#mermaid-svg-KUvGQa2rMEn5K3jm 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-KUvGQa2rMEn5K3jm .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-KUvGQa2rMEn5K3jm rect.text{fill:none;stroke-width:0;}#mermaid-svg-KUvGQa2rMEn5K3jm .icon-shape,#mermaid-svg-KUvGQa2rMEn5K3jm .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-KUvGQa2rMEn5K3jm .icon-shape p,#mermaid-svg-KUvGQa2rMEn5K3jm .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-KUvGQa2rMEn5K3jm .icon-shape .label rect,#mermaid-svg-KUvGQa2rMEn5K3jm .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-KUvGQa2rMEn5K3jm .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-KUvGQa2rMEn5K3jm .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-KUvGQa2rMEn5K3jm :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} TCP
字节流
应用要自己处理消息边界
UDP
数据报
每个包天然有边界
所谓"粘包"不是TCP犯错------TCP本来就是字节流,是应用层协议没设计好边界。不要怪TCP没按你的心理预期分段,它从来没承诺过。
九、典型应用场景速查表
| 场景 | 常用协议 | 原因 |
|---|---|---|
| Web页面(HTTP/1.1、HTTP/2) | TCP | 需要可靠、有序传输 |
| HTTPS | TCP | TLS传统运行在TCP上 |
| DNS查询 | UDP为主 | 小请求、小响应、低开销 |
| DNS区域传输/大响应 | TCP | 需要可靠或响应较大 |
| 视频直播 | UDP/基于UDP | 更看重实时性 |
| 在线游戏 | UDP常见 | 低延迟,应用自定义同步 |
| 语音通话 | UDP/RTP | 过期音频重传价值低 |
| 文件传输 | TCP常见 | 需要完整可靠 |
| HTTP/3 | UDP上的QUIC | 避免部分TCP问题,应用层实现可靠性 |
注意:某个场景不是"永远只能用某个协议"。DNS可用UDP也可用TCP,HTTP/3用UDP但不是裸UDP。现实是工程取舍题,有时还附带历史包袱。
十、为什么实时场景偏爱UDP?
实时场景里,延迟往往比完整性更重要。
语音通话示例:
某个音频包丢了,应用可以选择:
- 插值补偿
- 静音一小段
- 直接跳过
但如果等它重传,后面的音频都被拖住,用户体验更差。
#mermaid-svg-jTm2zrWHSbXsQdMq{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-jTm2zrWHSbXsQdMq .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-jTm2zrWHSbXsQdMq .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-jTm2zrWHSbXsQdMq .error-icon{fill:#552222;}#mermaid-svg-jTm2zrWHSbXsQdMq .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-jTm2zrWHSbXsQdMq .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-jTm2zrWHSbXsQdMq .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-jTm2zrWHSbXsQdMq .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-jTm2zrWHSbXsQdMq .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-jTm2zrWHSbXsQdMq .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-jTm2zrWHSbXsQdMq .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-jTm2zrWHSbXsQdMq .marker{fill:#333333;stroke:#333333;}#mermaid-svg-jTm2zrWHSbXsQdMq .marker.cross{stroke:#333333;}#mermaid-svg-jTm2zrWHSbXsQdMq svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-jTm2zrWHSbXsQdMq p{margin:0;}#mermaid-svg-jTm2zrWHSbXsQdMq .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-jTm2zrWHSbXsQdMq .cluster-label text{fill:#333;}#mermaid-svg-jTm2zrWHSbXsQdMq .cluster-label span{color:#333;}#mermaid-svg-jTm2zrWHSbXsQdMq .cluster-label span p{background-color:transparent;}#mermaid-svg-jTm2zrWHSbXsQdMq .label text,#mermaid-svg-jTm2zrWHSbXsQdMq span{fill:#333;color:#333;}#mermaid-svg-jTm2zrWHSbXsQdMq .node rect,#mermaid-svg-jTm2zrWHSbXsQdMq .node circle,#mermaid-svg-jTm2zrWHSbXsQdMq .node ellipse,#mermaid-svg-jTm2zrWHSbXsQdMq .node polygon,#mermaid-svg-jTm2zrWHSbXsQdMq .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-jTm2zrWHSbXsQdMq .rough-node .label text,#mermaid-svg-jTm2zrWHSbXsQdMq .node .label text,#mermaid-svg-jTm2zrWHSbXsQdMq .image-shape .label,#mermaid-svg-jTm2zrWHSbXsQdMq .icon-shape .label{text-anchor:middle;}#mermaid-svg-jTm2zrWHSbXsQdMq .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-jTm2zrWHSbXsQdMq .rough-node .label,#mermaid-svg-jTm2zrWHSbXsQdMq .node .label,#mermaid-svg-jTm2zrWHSbXsQdMq .image-shape .label,#mermaid-svg-jTm2zrWHSbXsQdMq .icon-shape .label{text-align:center;}#mermaid-svg-jTm2zrWHSbXsQdMq .node.clickable{cursor:pointer;}#mermaid-svg-jTm2zrWHSbXsQdMq .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-jTm2zrWHSbXsQdMq .arrowheadPath{fill:#333333;}#mermaid-svg-jTm2zrWHSbXsQdMq .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-jTm2zrWHSbXsQdMq .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-jTm2zrWHSbXsQdMq .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-jTm2zrWHSbXsQdMq .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-jTm2zrWHSbXsQdMq .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-jTm2zrWHSbXsQdMq .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-jTm2zrWHSbXsQdMq .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-jTm2zrWHSbXsQdMq .cluster text{fill:#333;}#mermaid-svg-jTm2zrWHSbXsQdMq .cluster span{color:#333;}#mermaid-svg-jTm2zrWHSbXsQdMq 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-jTm2zrWHSbXsQdMq .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-jTm2zrWHSbXsQdMq rect.text{fill:none;stroke-width:0;}#mermaid-svg-jTm2zrWHSbXsQdMq .icon-shape,#mermaid-svg-jTm2zrWHSbXsQdMq .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-jTm2zrWHSbXsQdMq .icon-shape p,#mermaid-svg-jTm2zrWHSbXsQdMq .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-jTm2zrWHSbXsQdMq .icon-shape .label rect,#mermaid-svg-jTm2zrWHSbXsQdMq .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-jTm2zrWHSbXsQdMq .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-jTm2zrWHSbXsQdMq .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-jTm2zrWHSbXsQdMq :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 实时音频包丢失
怎么办?
等待重传
延迟升高
跳过/补偿
保持实时
用户可能只听到轻微瑕疵
用户听到明显卡顿
在线游戏示例:
玩家位置更新每秒很多次。某一帧位置包丢了,下一帧很快就来了。重传旧位置反而没意义------你不能让游戏角色在200ms后认真补走刚才那一步,那不是同步,是鬼畜。
UDP给应用的自由:
| 应用可决定 | 说明 |
|---|---|
| 哪些消息必须可靠 | 重要消息走确认机制 |
| 哪些消息可以丢 | 不重要的可丢弃 |
| 哪些消息过期就不要 | 过时数据不重传 |
| 哪些消息需要重传 | 关键消息保证送达 |
| 哪些消息只要最新状态 | 只关心最新值 |
UDP的价值不是"不可靠所以差",而是"把可靠策略交给更懂业务的应用"。
十一、为什么文件传输偏爱TCP?
文件传输和实时语音完全相反------少一个字节都可能坏。
下载压缩包,中间少了一段,能不能"将就着看"?通常不能,该坏就是坏。
文件传输需要:
| 需求 | 说明 |
|---|---|
| 完整 | 一个字节都不能少 |
| 有序 | 字节顺序必须正确 |
| 不重复 | 不能收到重复数据 |
| 能重传 | 错了要能修复 |
这些正是TCP擅长的。
#mermaid-svg-cxunLTjlZGS4Biho{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-cxunLTjlZGS4Biho .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-cxunLTjlZGS4Biho .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-cxunLTjlZGS4Biho .error-icon{fill:#552222;}#mermaid-svg-cxunLTjlZGS4Biho .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-cxunLTjlZGS4Biho .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-cxunLTjlZGS4Biho .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-cxunLTjlZGS4Biho .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-cxunLTjlZGS4Biho .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-cxunLTjlZGS4Biho .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-cxunLTjlZGS4Biho .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-cxunLTjlZGS4Biho .marker{fill:#333333;stroke:#333333;}#mermaid-svg-cxunLTjlZGS4Biho .marker.cross{stroke:#333333;}#mermaid-svg-cxunLTjlZGS4Biho svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-cxunLTjlZGS4Biho p{margin:0;}#mermaid-svg-cxunLTjlZGS4Biho .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-cxunLTjlZGS4Biho .cluster-label text{fill:#333;}#mermaid-svg-cxunLTjlZGS4Biho .cluster-label span{color:#333;}#mermaid-svg-cxunLTjlZGS4Biho .cluster-label span p{background-color:transparent;}#mermaid-svg-cxunLTjlZGS4Biho .label text,#mermaid-svg-cxunLTjlZGS4Biho span{fill:#333;color:#333;}#mermaid-svg-cxunLTjlZGS4Biho .node rect,#mermaid-svg-cxunLTjlZGS4Biho .node circle,#mermaid-svg-cxunLTjlZGS4Biho .node ellipse,#mermaid-svg-cxunLTjlZGS4Biho .node polygon,#mermaid-svg-cxunLTjlZGS4Biho .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-cxunLTjlZGS4Biho .rough-node .label text,#mermaid-svg-cxunLTjlZGS4Biho .node .label text,#mermaid-svg-cxunLTjlZGS4Biho .image-shape .label,#mermaid-svg-cxunLTjlZGS4Biho .icon-shape .label{text-anchor:middle;}#mermaid-svg-cxunLTjlZGS4Biho .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-cxunLTjlZGS4Biho .rough-node .label,#mermaid-svg-cxunLTjlZGS4Biho .node .label,#mermaid-svg-cxunLTjlZGS4Biho .image-shape .label,#mermaid-svg-cxunLTjlZGS4Biho .icon-shape .label{text-align:center;}#mermaid-svg-cxunLTjlZGS4Biho .node.clickable{cursor:pointer;}#mermaid-svg-cxunLTjlZGS4Biho .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-cxunLTjlZGS4Biho .arrowheadPath{fill:#333333;}#mermaid-svg-cxunLTjlZGS4Biho .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-cxunLTjlZGS4Biho .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-cxunLTjlZGS4Biho .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-cxunLTjlZGS4Biho .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-cxunLTjlZGS4Biho .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-cxunLTjlZGS4Biho .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-cxunLTjlZGS4Biho .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-cxunLTjlZGS4Biho .cluster text{fill:#333;}#mermaid-svg-cxunLTjlZGS4Biho .cluster span{color:#333;}#mermaid-svg-cxunLTjlZGS4Biho 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-cxunLTjlZGS4Biho .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-cxunLTjlZGS4Biho rect.text{fill:none;stroke-width:0;}#mermaid-svg-cxunLTjlZGS4Biho .icon-shape,#mermaid-svg-cxunLTjlZGS4Biho .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-cxunLTjlZGS4Biho .icon-shape p,#mermaid-svg-cxunLTjlZGS4Biho .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-cxunLTjlZGS4Biho .icon-shape .label rect,#mermaid-svg-cxunLTjlZGS4Biho .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-cxunLTjlZGS4Biho .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-cxunLTjlZGS4Biho .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-cxunLTjlZGS4Biho :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 文件数据
TCP可靠传输
丢包重传
乱序重排
完整交付
文件可用
当然也可以用UDP自己实现可靠文件传输,但问题是:你真的想重新实现半个TCP吗?大多数普通业务不需要。技术选型不是才艺表演。
十二、抓包看TCP和UDP
抓TCP:
bash
tcpdump -i eth0 -nn tcp
抓UDP:
bash
tcpdump -i eth0 -nn udp
TCP抓包典型输出:
text
Flags [S] # SYN
Flags [S.] # SYN-ACK
Flags [.] # ACK
Flags [P.] # PSH-ACK
Flags [F.] # FIN-ACK
这些标志位代表连接建立、数据传输、关闭过程。
UDP抓包典型输出:
text
IP 192.168.1.10.5353 > 224.0.0.251.5353: UDP, length 32
UDP抓包更直接------没有三次握手,没有连接状态,就是一个个独立的数据报。
#mermaid-svg-ciOxHAe0noabvqKY{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-ciOxHAe0noabvqKY .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ciOxHAe0noabvqKY .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ciOxHAe0noabvqKY .error-icon{fill:#552222;}#mermaid-svg-ciOxHAe0noabvqKY .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ciOxHAe0noabvqKY .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ciOxHAe0noabvqKY .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ciOxHAe0noabvqKY .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ciOxHAe0noabvqKY .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ciOxHAe0noabvqKY .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ciOxHAe0noabvqKY .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ciOxHAe0noabvqKY .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ciOxHAe0noabvqKY .marker.cross{stroke:#333333;}#mermaid-svg-ciOxHAe0noabvqKY svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ciOxHAe0noabvqKY p{margin:0;}#mermaid-svg-ciOxHAe0noabvqKY .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-ciOxHAe0noabvqKY .cluster-label text{fill:#333;}#mermaid-svg-ciOxHAe0noabvqKY .cluster-label span{color:#333;}#mermaid-svg-ciOxHAe0noabvqKY .cluster-label span p{background-color:transparent;}#mermaid-svg-ciOxHAe0noabvqKY .label text,#mermaid-svg-ciOxHAe0noabvqKY span{fill:#333;color:#333;}#mermaid-svg-ciOxHAe0noabvqKY .node rect,#mermaid-svg-ciOxHAe0noabvqKY .node circle,#mermaid-svg-ciOxHAe0noabvqKY .node ellipse,#mermaid-svg-ciOxHAe0noabvqKY .node polygon,#mermaid-svg-ciOxHAe0noabvqKY .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ciOxHAe0noabvqKY .rough-node .label text,#mermaid-svg-ciOxHAe0noabvqKY .node .label text,#mermaid-svg-ciOxHAe0noabvqKY .image-shape .label,#mermaid-svg-ciOxHAe0noabvqKY .icon-shape .label{text-anchor:middle;}#mermaid-svg-ciOxHAe0noabvqKY .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-ciOxHAe0noabvqKY .rough-node .label,#mermaid-svg-ciOxHAe0noabvqKY .node .label,#mermaid-svg-ciOxHAe0noabvqKY .image-shape .label,#mermaid-svg-ciOxHAe0noabvqKY .icon-shape .label{text-align:center;}#mermaid-svg-ciOxHAe0noabvqKY .node.clickable{cursor:pointer;}#mermaid-svg-ciOxHAe0noabvqKY .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-ciOxHAe0noabvqKY .arrowheadPath{fill:#333333;}#mermaid-svg-ciOxHAe0noabvqKY .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-ciOxHAe0noabvqKY .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-ciOxHAe0noabvqKY .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ciOxHAe0noabvqKY .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-ciOxHAe0noabvqKY .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ciOxHAe0noabvqKY .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-ciOxHAe0noabvqKY .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ciOxHAe0noabvqKY .cluster text{fill:#333;}#mermaid-svg-ciOxHAe0noabvqKY .cluster span{color:#333;}#mermaid-svg-ciOxHAe0noabvqKY 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-ciOxHAe0noabvqKY .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-ciOxHAe0noabvqKY rect.text{fill:none;stroke-width:0;}#mermaid-svg-ciOxHAe0noabvqKY .icon-shape,#mermaid-svg-ciOxHAe0noabvqKY .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ciOxHAe0noabvqKY .icon-shape p,#mermaid-svg-ciOxHAe0noabvqKY .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-ciOxHAe0noabvqKY .icon-shape .label rect,#mermaid-svg-ciOxHAe0noabvqKY .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ciOxHAe0noabvqKY .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-ciOxHAe0noabvqKY .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-ciOxHAe0noabvqKY :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 抓包观察
TCP
UDP
SYN/SYN-ACK/ACK
序列号/确认号/重传
单个数据报
无连接建立过程
TCP很啰嗦,但啰嗦也有好处------留下的线索多。UDP很安静,排查时你也会更孤独。
十三、工程排查:TCP和UDP问题怎么定位?
TCP排查
TCP有连接过程,先看:
| 检查点 | 说明 |
|---|---|
| SYN有没有发出 | 客户端是否发起连接 |
| SYN-ACK有没有回来 | 服务端是否响应 |
| 是否出现RST | 连接被拒绝或重置 |
| 三次握手是否完成 | 连接是否建立成功 |
| 是否有重传 | 网络是否丢包 |
| 窗口是否很小 | 接收方处理能力不足 |
| 是否被防火墙拦截 | 安全策略问题 |
常用命令:
bash
ss -antp # 查看TCP连接状态
nc -vz 目标IP 端口 # TCP端口探测
curl -v http://目标IP:端口 # HTTP测试
抓包:
bash
tcpdump -i eth0 -nn tcp port 80
UDP排查
UDP没有连接建立,需要看:
| 检查点 | 说明 |
|---|---|
| 数据报是否发出 | 本机是否发送成功 |
| 对端是否收到 | 需要在接收端抓包确认 |
| 应用是否处理 | 检查应用日志 |
| 是否有ICMP Port Unreachable | 目标端口未监听 |
| 是否被防火墙丢弃 | 检查防火墙规则 |
| 应用层是否有自己的ACK | 应用级确认机制 |
常用命令:
bash
nc -u 目标IP 端口 # UDP发送测试
抓包:
bash
tcpdump -i eth0 -nn udp port 53
UDP排查特别注意:没有响应不一定代表包没到。可能是应用没回、回包被拦、或者协议本来就不要求每包回应。
TCP像有聊天记录,UDP像在广场喊一句------有没有人听见,要看现场。
十四、五大常见误区
误区一:TCP一定比UDP慢
不一定。TCP有更多机制,理论开销更大,但实际性能取决于网络质量、应用设计、拥塞控制算法等。一个设计糟糕的UDP应用,可能比TCP更慢、更不稳定。UDP不会自动让系统变快,它只是给更多控制权------控制权给错人,事故也更自由。
误区二:UDP不会丢包(因为局域网很稳)
不对。UDP本身不保证不丢。在某些局域网环境里丢包概率低,但低概率不等于协议保证。每天过马路没出事,不代表交通规则可以删掉。
误区三:TCP是消息协议
不对 。TCP是字节流协议,不保留应用写入时的消息边界。所谓"粘包""半包"不是TCP坏,是你误会了它。
误区四:UDP不能做可靠传输
不对。UDP协议本身不提供可靠性,但应用可以在UDP上实现可靠传输。QUIC就是重要例子。问题不是"能不能",是"你是否真的需要自己做,以及能不能做好"。
误区五:可靠性越强越好
不一定。实时音视频、游戏状态同步等场景里,过期数据重传可能不如直接丢弃。可靠性是目标之一,不是唯一目标。工程里经常要在可靠、延迟、吞吐、成本之间做取舍------没有银弹,只有账单。
十五、小结
| 序号 | 核心结论 |
|---|---|
| 1 | TCP和UDP都是传输层协议,运行在IP之上 |
| 2 | TCP面向连接,UDP无连接 |
| 3 | TCP提供可靠、有序、字节流传输 |
| 4 | UDP提供尽力而为的数据报传输 |
| 5 | TCP的可靠性来自序列号、ACK、重传、流量控制、拥塞控制 |
| 6 | UDP本身不可靠,但应用可在其上实现可靠策略(如QUIC) |
| 7 | TCP不保留消息边界,UDP保留数据报边界(关键区别!) |
| 8 | 实时场景偏爱UDP------过期数据价值低 |
| 9 | 文件传输使用TCP------完整性更重要 |
| 10 | 协议选择不是谁更高级,是看谁更适合场景 |
最后一句话总结:TCP把可靠性内置在传输层,UDP把选择权交给应用层。
可靠和速度不是简单对立。真正的工程选择,是在具体场景里决定哪些东西必须可靠,哪些东西可以更快。
十六、下篇预告
第14篇:端口------进程的"门牌号"
- IP地址能找到主机,那一台主机上那么多进程,数据到底该交给谁?
- 为什么HTTP默认是80,HTTPS默认是443?
- 为什么端口被占用会导致服务启动失败?
下一篇,我们继续拆"主机内部分发"的问题。
如果觉得有帮助,欢迎点赞、收藏、评论区交流讨论!