type: learning-note
title: Linux:传输层与三次握手(TCP vs UDP、端口与套接字、SYN → SYN-ACK → ACK)
date: 2026-10-23
description:传输层管到程序而非机器、端口 16 位与监听套接字、五元组唯一标识连接、TCP 有序可靠字节流、不保留消息边界、可靠≠绝对送达、UDP 数据报与校验和、UDP 不必然更快、三次握手三步(SYN/SYN-ACK/ACK)、握手证明什么没证明什么
2026-10-23 学习笔记
> 📌 GitHub:https://github.com/AR-firefly
笔记区
核心观点
**传输层:把包交给程序,不是交给机器**
- 网际层(IP)只认"哪台机器",把包送到机器门口;传输层认"哪个程序",把包交到机器上对应的程序。
「传输层是为了让信息进入机器后能再把信息传给程序,否则程序得不到信息,网际层是给机器与机器直接交流的东西」
-
**端点**:一段对话的一头。两台程序说话,各占一头,合起来是两个端点。
-
原文(LJ `transport-layer`):
> **英文原句**:The transport layer connects application endpoints across an IP network.
> **中文翻译**:传输层通过 IP 网络连接应用程序端点。
> **说人话**:IP 只把包送到机器门口;传输层负责把这包交到机器上具体哪个程序手里。
**端口:程序在机器上的号码**
-
端口是 **16 位** → 2¹⁶ = **65536** 个编号,范围 **0--65535**。
-
16 位 = 16 个二进制格子,每格 0 或 1 → 2¹⁶ = 65536 种组合。
-
这套算法与 2026-10-22 算 `/20` 主机位的 2¹² 相同。
-
**监听**:程序想收数据,先在一个端口号上等着,这叫监听。
-
包到了机器,系统看包里的**目标端口号**,交给正在那个号码上监听的程序。
「机器上有多个号码,号码数量为2的16次方,程序在这等着,等的位置叫端口,等的行为叫监听,包到了后,上面写着对应的号码,系统根据号码把包送给程序」
- 原文:
> **英文原句**:A destination port helps the operating system deliver traffic to a listening socket.
> **中文翻译**:目标端口帮助操作系统把流量送达监听套接字。
> **说人话**:包身上写着"送到几号房间",系统就把它交到那个房间里等着的程序手上。
**五元组:唯一认出一条连接**
- 只看一个端口分不出谁是谁;要认出"这是哪条连接"需要五项:
| 项 | 例子 |
| -------- | ------------ |
| 协议 | TCP |
| 源 IP | 192.168.1.10 |
| 源端口 | 50001 |
| 目的 IP | 1.2.3.4 |
| 目的端口 | 443 |
-
两个客户端同时连同一台服务器:目的 IP + 目的端口一样,靠**源 IP + 源端口**不同区分。
-
**套接字**:一个端点 = IP + 端口;五元组 = 两个套接字 + 协议。
五元组**不是层层细分**(省 / 市 / 县那种),是**五个并列字段**组合起来。
- 原文:
> **英文原句**:A connection or flow is identified by more than one port: protocol, source and destination addresses, and source and destination ports all matter. The same server port can therefore support many simultaneous clients.
> **中文翻译**:一条连接或流量不能只靠一个端口来标识:协议、源地址与目标地址、源端口与目标端口都很重要。因此同一个服务器端口可以同时支持许多客户端。
> **说人话**:认出"这是哪条连接"要看五个信息,不是只看一个端口号。
**TCP:有序、可靠、字节流**
- 三个保证:
| 保证 | 什么意思 |
| ---------- | ---------------------------------------------- |
| **有序** | 发出去是第 1、2、3 段,收到的也按 1、2、3 排好 |
| **可靠** | 丢了的会重发,收到会回执 |
| **字节流** | 眼里只有"一串字节",没有"一条条消息" |
-
手段:**序列号**(给字节编号)、**确认 ACK**(收到了就回)、**超时重传**(没回执就再发)。
-
`流量控制` / `拥塞控制` 只记名字,用到再查 `man 7 tcp`。
-
原文:
> **英文原句**:TCP provides an ordered, reliable byte stream while a connection remains viable. It uses sequence numbers, acknowledgements, retransmission, flow control, and congestion control.
> **中文翻译**:只要连接仍然可用,TCP 就提供有序、可靠的字节流。它使用序列号、确认、重传、流量控制、拥塞控制。
> **说人话**:TCP 给你一条"按顺序、不丢、连着不断"的数据管道,靠编号和回执来做到。
**TCP 不保留消息边界**
-
一次写入可能通过多次读取到达;多次写入也可能由一次读取返回。
-
应用层必须自己规定"一条消息到哪结束"(成帧 / framing)。
-
注意:TCP **不会改内容、不会乱顺序**;丢的是"分界"。反例:`hello world` 不会被拆成 `hell owo rld`(那等于改内容);真实情况是两条消息"你好"+"在吗"被一次读成"你好在吗"。
-
原文:
> **英文原句**:TCP does not preserve application message boundaries: one write can arrive through several reads, or several writes can be returned by one read. Applications define their own framing.
> **中文翻译**:TCP 不保留应用程序消息边界:一次写入可能通过多次读取到达,多次写入也可能由一次读取返回。应用程序必须自行定义成帧方式。
> **说人话**:TCP 只管把这串字节按顺序送到,不管你一封信用了几次发、对方分几次收。
**"可靠"不等于"绝对送达"**
-
连接会**超时**、被**重置**(RST)、或失败;重传不是无限的。
-
**ACK 只证明对方传输层收到**,不证明对方应用处理了。
「收到不代表成功,收到了只是说明人家刚刚开始处理,甚至收到就挂机不干了,永远处理不了」
- 原文:
> **英文原句**:Reliability is not absolute delivery. A connection can time out, reset, or fail, and an acknowledgement does not prove that an application durably committed the data.
> **中文翻译**:可靠并不等于绝对送达。连接可能超时、重置或失败,而且确认并不能证明应用程序已持久提交了数据。
> **说人话**:TCP 的"可靠"只管到传输层为止,管不到"对方程序是不是真把东西存下来了"。
**UDP:数据报**
-
**有**:保留**数据报边界**(一次发一份,收也是一份)、**校验和**(能发现数据坏了)。
-
**没有**:连接状态、排序、重传、流量控制、拥塞控制。
-
要可靠性、要重传,**应用自己加**。
-
原文:
> **英文原句**:UDP preserves datagram boundaries and provides checksum-based error detection, but it does not provide TCP-style connection state, ordering, retransmission, flow control, or congestion control. An application can add any needed reliability or congestion behavior itself.
> **中文翻译**:UDP 保留数据报边界,并提供基于校验和的错误检测,但不提供 TCP 式的连接状态、排序、重传、流量控制或拥塞控制。应用程序可以自行添加所需的可靠性或拥塞行为。
> **说人话**:UDP 一次发一份,一份就是一份;但它不排队、不重发、不管对面忙不忙。
**UDP 并不必然更快**
-
性能取决于四项:**协议设计、工作负载、路径、实现**。
-
同一份 UDP 代码、同样数据量,A 机房比 B 机房慢很多 → 四项里**路径**不同(代码相同排除实现与设计,数据量相同排除负载)。
-
原文:
> **英文原句**:UDP is not automatically faster; performance depends on protocol design, workload, path, and implementation.
> **中文翻译**:UDP 并不自动更快;性能取决于协议设计、工作负载、路径和实现。
> **说人话**:少了几道手续,不等于结果更快。
**三次握手:连接怎么建立**
- 三步:
| 步 | 谁发给谁 | 带什么 |
| ----------- | --------------- | ------------------------------------ |
| ① `SYN` | 发起方 → 监听方 | 我的**初始序列号** |
| ② `SYN-ACK` | 监听方 → 发起方 | 我的**序列号** + **确认(ACK)你的** |
| ③ `ACK` | 发起方 → 监听方 | 确认你的 |
-
结果:**两端各自建立传输状态**。
-
「SYN,SYN+ACK和ACK,因为一次文件可以发送多个信息,第二次直接发SYN+ACK,省一次」
-
纠正:"一次**报文**"可以同时携带 SYN 和 ACK 两个标志,不是"一次文件"。
-
原文:
> **英文原句**:A normal TCP connection begins with a three-way handshake: 1. The initiator sends `SYN` with its initial sequence information. 2. The listener replies `SYN-ACK` with its own sequence information and acknowledgement. 3. The initiator returns `ACK`.
> **中文翻译**:正常的 TCP 连接以三次握手开始:1. 发起方发送带有初始序列信息的 `SYN`。2. 监听方回复 `SYN-ACK`,带上自己的序列信息和确认。3. 发起方返回 `ACK`。
> **说人话**:我报个起始编号给你,你收下、也报你的编号给我,我再说一声收到了 ------ 两边编号就对齐了。
**握手证明什么、没证明什么**
| 证明了 | 没证明 |
| ------------------------ | ------------------------------------ |
| 两头都能收发(双向可达) | 对面的**身份**(可能是假冒的服务器) |
| 编号起点对齐 | 对面**应用**能处理你的请求 |
| 两端各自建立传输状态 | 请求会成功 |
-
「连接只保证你能连接上不保证你成不成功」
-
原文:
> **英文原句**:This establishes transport state in both endpoints. It does not authenticate the application server or prove that the requested application operation will succeed.
> **中文翻译**:该过程在两个端点中建立传输状态。它不会验证应用服务器的身份,也不能证明所请求的应用操作会成功。
> **说人话**:握手只证明两头能互相收发、编号对上了;它不证明对面是谁,也不证明对面能替你办事。
关键方法/流程
**三次握手三步(带序列号)**
-
发起方 → 监听方:`SYN`,初始序列号 x
-
监听方 → 发起方:`SYN-ACK`,自己的序列号 y,确认号 x+1
-
发起方 → 监听方:`ACK`,确认号 y+1
-
**为什么三次不是四次**:第二步的 `SYN` 和 `ACK` 合并进同一个报文,省掉一次。
-
**为什么不是两次**:两次只能确认一方的编号,另一方的编号没被确认。
**一个端口怎么服务多个客户端**
-
目的 IP + 目的端口对所有客户端相同
-
源 IP + 源端口各不相同
-
五元组合起来唯一 → 一个监听端口可承载多条并发连接
实战记录
**① `grep -C 3` 对比:不带上下文 vs 带上下文**
不带上下文:
```
grep -n 'restart counter' /var/log/syslog | head -10
```
跑出来的输出(节选):
```
46:2026-10-18T10:13:21.062058+08:00 AR-firefly systemd1: wsl-pro.service: Scheduled restart job, restart counter is at 59.
61:2026-10-18T10:44:27.577990+08:00 AR-firefly systemd1: wsl-pro.service: Scheduled restart job, restart counter is at 60.
...
487:2026-10-18T21:49:29.725744+08:00 AR-firefly systemd1: wsl-pro.service: Scheduled restart job, restart counter is at 68.
```
带上下文:
```
grep -n -C 3 'restart counter' /var/log/syslog | head -30
```
多出来的关键行:
```
58-2026-10-18T10:24:27.029726+08:00 AR-firefly wsl-pro-service7090: WARNING Exiting after <nil>: check if the Windows agent is installed and running.
59-2026-10-18T10:24:27.032789+08:00 AR-firefly systemd1: wsl-pro.service: Deactivated successfully.
60-2026-10-18T10:24:27.033642+08:00 AR-firefly systemd1: wsl-pro.service: Consumed 1.611s CPU time over 31min 6.044s wall clock time, 61M memory peak.
```
-
不带 `-C 3`:只看到"它每 31 分钟被重启一次",看不出原因。
-
带上 `-C 3`:看到 `WARNING Exiting ... check if the Windows agent is installed and running` ------ 它因为 Windows agent 不可用而退出,systemd 再拉起来。
-
**`-C 3` 给的是候选上下文,不是答案**:同一段里也混着 `chronyd`、`systemd-resolved` 的无关行,要自己挑。
**② 三次握手报文排序**
给三个打乱的报文:
-
报文 A:`ACK`,确认号 x+1
-
报文 B:`SYN`,序列号 x
-
报文 C:`SYN-ACK`,序列号 y,确认号 x+1
排出的顺序:**B(初始序列号)→ C(序列号 + 确认对方)→ A(确认对方)**
线索区(学完后合上材料,自问自答)
**Q: 传输层和网际层的分工是什么?**
A: IP 管到机器;传输层管到程序。包到了机器还没到程序,传输层负责交到对应的程序。
**Q: 端口是几位、一共多少个、范围是多少?**
A: 16 位;2¹⁶ = 65536 个;0--65535。
**Q: 包到了机器上,系统看哪一项决定交给哪个程序?**
A: 包里的**目标端口号**,按号码交给正在那个号码上监听的程序。
**Q: 五元组是哪五项?为什么需要五个?**
A: 协议 + 源 IP + 源端口 + 目的 IP + 目的端口。只看端口分不出哪条连接是哪条;目的那侧相同时,靠源 IP + 源端口区分。
**Q: TCP 保证哪三件事?靠什么手段做到?**
A: 有序(序列号)、可靠(ACK + 超时重传)、字节流;另有流量控制、拥塞控制。
**Q: 用 TCP 一次写 100 字节,对方分两次读到 60 + 40,可能吗?为什么?**
A: 可能。写的次数和读的次数没有对应关系;TCP 不保留消息边界。
**Q: TCP 会改内容和顺序吗?**
A: 不会。它保证内容和顺序,丢的是"分界",不是"内容"。
**Q: 收到 ACK 就等于对方应用处理完了吗?为什么?**
A: 不等于。ACK 只证明对方传输层收到了;应用可能还没处理、处理失败,或收到就崩了。
**Q: UDP 保留了哪样、缺了哪几样?**
A: 保留数据报边界、有校验和;缺连接状态、排序、重传、流量控制、拥塞控制。
**Q: UDP 丢了包谁补?**
A: 应用自己。UDP 不重传、不通知。
**Q: UDP 一定比 TCP 快吗?**
A: 不一定。看协议设计、工作负载、路径、实现四项。
**Q: 三次握手三步各带什么信息?**
A: `SYN` 带初始序列号;`SYN-ACK` 带自己的序列号和对方的确认;`ACK` 确认对方。
**Q: 为什么是三次不是四次?**
A: 第二步的 `SYN` 和 `ACK` 可以合在同一个报文里。
**Q: 握手证明了什么、没证明什么?**
A: 证明双向可达、编号对齐、两端建立传输状态;不证明对方身份、应用能处理、请求会成功。
**Q: "通了"和"能用"差在哪?**
A: 通 = 传输层两端能收发;能用 = 应用层真的处理请求并成功返回。握手的证据只到前者。
总结(50字以内,用自己的话概括今天学到了什么)
IP 送到机器,端口送到程序;TCP 用编号和回执保有序可靠,UDP 留边界不补丢;三次握手对齐编号,只证明通不证明能用。
复习卡片
| 概念 | 必学/了解 | 一句话 | 场景 |
| ------------------- | --------- | ------------------------------------------- | ------------------------ |
| 传输层 | 必学 | 把流量交给应用程序端点,不是交给机器 | 分清机器不通还是程序不通 |
| 应用程序端点 | 必学 | 一段对话的一头;两台程序各占一头 | 描述连接两端 |
| 端口 | 必学 | 程序在机器上的号码,16 位 → 0--65535 | 找哪个程序在收 |
| 监听 | 必学 | 程序在某个端口号上等着收数据 | 判断服务在不在 |
| 目标端口 | 必学 | 系统据此把包交给对应程序 | 读包、读 ss |
| 套接字 | 必学 | 一个端点 = IP + 端口 | 描述连接 |
| 五元组 | 必学 | 协议 + 两 IP + 两端口 = 5 项 | 唯一认出连接 |
| TCP | 必学 | 传输层协议:有序、可靠、字节流 | 判断能不能忍丢 |
| 字节流 | 必学 | 一串字节,没有消息分界 | 解释为什么要成帧 |
| 序列号 | 必学 | 给字节编号,用于排序和发现缺失 | 解释有序与重传 |
| ACK | 必学 | 收到的回执;只到传输层 | 判断"收到≠处理" |
| 消息边界 | 必学 | 一条消息到哪结束;TCP 不保留 | 应用协议必须自己定 |
| 可靠 ≠ 绝对送达 | 必学 | 会超时、重置、失败;ACK 不证明应用提交 | 排障不误判 |
| 重置 / RST | 必学 | 连接被强制掐断,对比 FIN 正常关闭 | 看连接异常断 |
| UDP | 必学 | 传输层协议:保留数据报边界、有校验和 | 判断要不要 TCP |
| 数据报 | 必学 | 一份独立数据,自带边界 | 解释 UDP 的边界 |
| 校验和 | 了解 | 发现数据坏了的校验值;`man 7 udp` | 锚点,用到再讲 |
| 工作负载 | 了解 | 系统要处理多少活、多频繁 | 判断性能 |
| SYN | 必学 | Synchronize 前三个字母;"我要和你对表" | 看握手第一个报文 |
| SYN-ACK | 必学 | 一个报文同时做同步和确认 | 看握手第二个报文 |
| 三次握手 | 必学 | SYN → SYN-ACK → ACK,两端建立传输状态 | 讲清连接建立 |
| 握手不证明什么 | 必学 | 不验证身份、不证明应用操作成功 | 判断服务可用 |
| 流量控制 / 拥塞控制 | 了解 | TCP 的两套调速机制;`man 7 tcp` | 锚点,用到再讲 |
| `ss` | 了解 | 看监听与已连接套接字;第 4 天讲;`man 8 ss` | 预览 |
| `/etc/services` | 了解 | 端口名对照表;`man 5 services` | 预览 |
流程附加段
旧知识回收
| 概念 | 一句话 | 出处 |
| ------------ | ------------------------------------------ | ----------------------------------------------- |
| 端口分拣 | 系统看目标端口,交给监听它的程序 | 收尾检索第 2 问先说"不知道",补讲后重考答"端口" |
| TCP 三保证 | 有序 / 可靠 / 字节流;序列号 + ACK + 重传 | 收尾检索第 4 问不知道,补讲后重考答全 |
| 五元组内容 | 协议 + 源 IP + 源端口 + 目的 IP + 目的端口 | 收尾检索第 3 问说"分别是啥记不得了",当场补 |
| 四因素 | 设计 / 负载 / 路径 / 实现 | 收尾检索第 8 问漏"工作负载",当场补 |
| TCP 不改内容 | 只丢分界,不会把 hello world 拆乱 | 收尾检索第 5 问例子举错,当场纠 |
今日产出验收
| 产出项(来源 `S1块4开周清单.md:67`) | 用户的回答 | 判定 |
| -------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | ---- |
| 讲清三次握手三步(含序列信息) | 「SYN,SYN+ACK和ACK」「B带初始序列号,C序列号 + 确认对方的ACK,A确认对方的ACK」 | ✅ |
| 说清它证明了什么、没证明什么 | 「证明两头都能收发,编号起点对齐,两端建立传输状态,但不知道对方是身份,不一定成功,对面也不一定能处理你的请求」 | ✅ |
| 说清 TCP 与 UDP 差在哪(可靠 / 有序 / 边界) | 「有序,可靠,字节流......UDP 保留信息边界和校验和,少了连接状态,排序,重传和流量控制 / 拥塞控制」 | ✅ |