<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>可靠传输 on CrashMemo | IT运维经验站</title><link>https://crashmemo.com/tags/%E5%8F%AF%E9%9D%A0%E4%BC%A0%E8%BE%93/</link><description>Recent content in 可靠传输 on CrashMemo | IT运维经验站</description><generator>Hugo -- gohugo.io</generator><language>zh</language><lastBuildDate>Tue, 07 Jul 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://crashmemo.com/tags/%E5%8F%AF%E9%9D%A0%E4%BC%A0%E8%BE%93/index.xml" rel="self" type="application/rss+xml"/><item><title>网络修炼笔记：可靠传输与深入 TCP 三次握手</title><link>https://crashmemo.com/p/tcp-three-way-handshake-deep-analysis/</link><pubDate>Tue, 07 Jul 2026 00:00:00 +0000</pubDate><guid>https://crashmemo.com/p/tcp-three-way-handshake-deep-analysis/</guid><description>&lt;h2 id="实验环境与物理拓扑"&gt;实验环境与物理拓扑
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;模拟器&lt;/strong&gt;：华为 eNSP&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;实验拓扑&lt;/strong&gt;：Client（客户端） ↔ SW1（交换机） ↔ Server（服务器）&lt;/li&gt;
&lt;/ul&gt;

 &lt;blockquote&gt;
 &lt;p&gt;若Client和Server两台设备直接相连，数据抓包选项会呈灰色不可点击状态。因此，中间必须加一台二层交换机，此时抓取交换机与任意端连接的接口即可顺利开启 Wireshark。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;网络层（IP）规划&lt;/strong&gt;：&lt;/li&gt;
&lt;li&gt;Client IP：&lt;code&gt;192.168.1.1&lt;/code&gt;，子网掩码：&lt;code&gt;255.255.255.0&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Server IP：&lt;code&gt;192.168.1.2&lt;/code&gt;，子网掩码：&lt;code&gt;255.255.255.0&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;应用层（Service）规划&lt;/strong&gt;： Server 开启标准的 &lt;strong&gt;FTP（文件传输服务）&lt;/strong&gt;，默认监听 &lt;strong&gt;21&lt;/strong&gt; 端口。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="TCP 三次握手实验拓扑图" class="gallery-image" data-flex-basis="798px" data-flex-grow="332" height="330" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://crashmemo.com/p/tcp-three-way-handshake-deep-analysis/PixPin_2026-07-07_16-35-00.webp" srcset="https://crashmemo.com/p/tcp-three-way-handshake-deep-analysis/PixPin_2026-07-07_16-35-00_hu_2613d6fc8391994c.webp 800w, https://crashmemo.com/p/tcp-three-way-handshake-deep-analysis/PixPin_2026-07-07_16-35-00.webp 1098w" width="1098"&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="理论前置tcp-报文头结构与核心控制位"&gt;理论前置：TCP 报文头结构与核心控制位
&lt;/h2&gt;&lt;h3 id="标志位flags-决定这个包的性质"&gt;标志位（Flags）—— 决定这个包的“性质”
&lt;/h3&gt;&lt;p&gt;TCP 头部有一组控制位（共 6 个或更多，占用 1 个字节左右的空间），它们就像开关一样，置为 &lt;code&gt;1&lt;/code&gt; 表示启用：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;SYN (Synchronize)&lt;/strong&gt;：&lt;strong&gt;同步标志位&lt;/strong&gt;。当启动一个新连接时，此位必须置为 1。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ACK (Acknowledgment)&lt;/strong&gt;：&lt;strong&gt;确认标志位&lt;/strong&gt;。除了第一个发起连接的包之外，后续所有在网上传输的 TCP 包，该位都必须置为 1，表示“确认号（Ack Number）有效”。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="序号seq与确认号ack-决定数据的顺序"&gt;序号（Seq）与确认号（Ack）—— 决定数据的“顺序”
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Sequence Number (Seq)&lt;/strong&gt;：&lt;strong&gt;序列号&lt;/strong&gt;。由发送端随机生成的计数器，用来告诉接收端：“本报文段所发送的数据的第一个字节的编号是多少”。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Acknowledgment Number (Ack)&lt;/strong&gt;：&lt;strong&gt;确认号&lt;/strong&gt;。接收端用来告诉发送端：“你之前发的包我安全收到了，我期望你下一次从哪个字节开始发起”。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="实验配置与抓包步骤"&gt;实验配置与抓包步骤
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;服务器端配置&lt;/strong&gt;：双击 Server → 切换到 &lt;code&gt;ServerInfo&lt;/code&gt; 选项卡 → 点击左侧 &lt;code&gt;FtpServer&lt;/code&gt; → 选择一个本地文件夹作为 FTP 根目录 → 点击 &lt;code&gt;Start&lt;/code&gt; 启动。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Server 配置 FTP 服务并启动" class="gallery-image" data-flex-basis="346px" data-flex-grow="144" height="1018" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://crashmemo.com/p/tcp-three-way-handshake-deep-analysis/PixPin_2026-07-07_16-39-14.webp" srcset="https://crashmemo.com/p/tcp-three-way-handshake-deep-analysis/PixPin_2026-07-07_16-39-14_hu_8af28f35625afa47.webp 800w, https://crashmemo.com/p/tcp-three-way-handshake-deep-analysis/PixPin_2026-07-07_16-39-14.webp 1468w" width="1468"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;开启抓包&lt;/strong&gt;：右键点击交换机连接的物理接口，选择 &lt;code&gt;开始抓包&lt;/code&gt; 激活 Wireshark。&lt;/p&gt;
&lt;p&gt;&lt;img alt="交换机接口开启 Wireshark 抓包" class="gallery-image" data-flex-basis="1013px" data-flex-grow="422" height="258" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://crashmemo.com/p/tcp-three-way-handshake-deep-analysis/PixPin_2026-07-07_16-40-58.webp" srcset="https://crashmemo.com/p/tcp-three-way-handshake-deep-analysis/PixPin_2026-07-07_16-40-58_hu_6126c279e13345db.webp 800w, https://crashmemo.com/p/tcp-three-way-handshake-deep-analysis/PixPin_2026-07-07_16-40-58.webp 1089w" width="1089"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;客户端发起连接&lt;/strong&gt;：双击 Client → 切换到 &lt;code&gt;ClientInfo&lt;/code&gt; → 点击左侧 &lt;code&gt;FtpClient&lt;/code&gt; → 在 Server Address 栏输入 &lt;code&gt;192.168.1.2&lt;/code&gt;，Port 输入 &lt;code&gt;21&lt;/code&gt; → 点击 &lt;code&gt;登录&lt;/code&gt; 按钮。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Client 连接 FTP 服务器" class="gallery-image" data-flex-basis="346px" data-flex-grow="144" height="1018" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://crashmemo.com/p/tcp-three-way-handshake-deep-analysis/PixPin_2026-07-07_16-40-33.webp" srcset="https://crashmemo.com/p/tcp-three-way-handshake-deep-analysis/PixPin_2026-07-07_16-40-33_hu_edfccbff69cff31b.webp 800w, https://crashmemo.com/p/tcp-three-way-handshake-deep-analysis/PixPin_2026-07-07_16-40-33.webp 1468w" width="1468"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;过滤报文&lt;/strong&gt;：在 Wireshark 的过滤器中输入小写的 &lt;code&gt;tcp&lt;/code&gt;，回车锁定最开始触发的三条报文。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Wireshark 过滤 TCP 三次握手报文" class="gallery-image" data-flex-basis="1567px" data-flex-grow="652" height="351" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://crashmemo.com/p/tcp-three-way-handshake-deep-analysis/PixPin_2026-07-07_16-46-35.webp" srcset="https://crashmemo.com/p/tcp-three-way-handshake-deep-analysis/PixPin_2026-07-07_16-46-35_hu_3186a9e048dc304c.webp 800w, https://crashmemo.com/p/tcp-three-way-handshake-deep-analysis/PixPin_2026-07-07_16-46-35_hu_a819c910d5fc328a.webp 1600w, https://crashmemo.com/p/tcp-three-way-handshake-deep-analysis/PixPin_2026-07-07_16-46-35.webp 2292w" width="2292"&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="深度解剖三次握手时序数据对齐与状态机转换"&gt;深度解剖：三次握手时序、数据对齐与状态机转换
&lt;/h2&gt;&lt;p&gt;以下为真实实验环境下捕获到的三次握手核心报文完整数据：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;27 56.891000 192.168.1.1 192.168.1.2 TCP 58 2055 → 21 [SYN] Seq=0 Win=8192 Len=0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;28 56.906000 192.168.1.2 192.168.1.1 TCP 58 21 → 2055 [SYN, ACK] Seq=0 Ack=1 Win=8192 Len=0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;29 56.906000 192.168.1.1 192.168.1.2 TCP 54 2055 → 21 [ACK] Seq=1 Ack=1 Win=8192 Len=0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="第一次握手no-27-报文"&gt;第一次握手（No. 27 报文）
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;方向&lt;/strong&gt;：Client（&lt;code&gt;192.168.1.1&lt;/code&gt;） → Server（&lt;code&gt;192.168.1.2&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;报文核心字段&lt;/strong&gt;：&lt;code&gt;Flags = [SYN], Seq = 0, Ack = 0&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;操作系统状态转换&lt;/strong&gt;：Server 本来在 LISTEN（监听）；Client 把包发出去后，自身状态瞬间切换为 SYN_SENT（同步已发送）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;“服务器你好，我是 2055 端口。我想和你建立连接，这是我发给你的第一个包，我的编号是 0，收到请回答。”&lt;/p&gt;
&lt;h3 id="第二次握手no-28-报文"&gt;第二次握手（No. 28 报文）
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;方向&lt;/strong&gt;：Server（&lt;code&gt;192.168.1.2&lt;/code&gt;） → Client（&lt;code&gt;192.168.1.1&lt;/code&gt;）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;报文核心字段&lt;/strong&gt;：&lt;code&gt;Flags = [SYN, ACK], Seq = 0, Ack = 1&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;状态转换&lt;/strong&gt;：Server 收到请求后，在系统底层开辟一块临时缓存，状态切换为 SYN_RCVD（同步已接收）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;数字逻辑&lt;/strong&gt;：&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;Ack = 1&lt;/code&gt; 的由来&lt;/strong&gt;：Server 将客户端发来的 &lt;code&gt;Seq = 0&lt;/code&gt; 执行了 &lt;strong&gt;加 1&lt;/strong&gt; 操作（0+1=1），通过 &lt;code&gt;Ack = 1&lt;/code&gt; 明确告诉客户端：“你编号为 0 的包我拿到了，接下来我管你要编号为 1 的包。”&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;Seq = 0&lt;/code&gt; 的由来&lt;/strong&gt;：这是服务器自己作为一个独立的发送端，生成属于服务器侧的初始序列号。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;“客户端你好，我收到你的申请了，我同意。你刚刚给我的 0 号包我已经盖章确认了，下次请发 1 号包。同时，这也是我发给你的第一个包，我自身的编号是 0。”&lt;/p&gt;
&lt;h3 id="第三次握手no-29-报文"&gt;第三次握手（No. 29 报文）
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;方向&lt;/strong&gt;：Client（&lt;code&gt;192.168.1.1&lt;/code&gt;） → Server（&lt;code&gt;192.168.1.2&lt;/code&gt;）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;报文核心字段&lt;/strong&gt;：&lt;code&gt;Flags = [ACK], Seq = 1, Ack = 1&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;操作系统状态转换&lt;/strong&gt;：Client 收到服务器的同意答复，认为双向通信没问题，状态到最高级：ESTABLISHED（连接已建立）。当这个包送到 Server 后，Server 的状态也同步变成 ESTABLISHED。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;数字逻辑&lt;/strong&gt;：&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;Seq = 1&lt;/code&gt; 的由来&lt;/strong&gt;：完美响应了上一步服务器索要 &lt;code&gt;Ack = 1&lt;/code&gt; 的请求。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;Ack = 1&lt;/code&gt; 的由来&lt;/strong&gt;：Client 将服务器发来的 &lt;code&gt;Seq = 0&lt;/code&gt; 执行了 &lt;strong&gt;加 1&lt;/strong&gt; 操作（0+1=1），告诉服务器：“你刚才发给我的服务器 0 号包我也拿到了，下次请发 1 号包。”&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;“服务器，你的同意答复我收到了！瞧，这就是你管我要的 1 号包（Seq=1）。你刚刚给我的服务器 0 号包我也盖章确认了。握手圆满结束，我们开始干正事传文件吧！”&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="结论"&gt;结论
&lt;/h2&gt;&lt;p&gt;握手的核心是同步序号：三次握手不仅是打招呼，最重要的是在物理不可靠的网路上，通过 Seq 和 Ack 的加 1 联动，在两端同步一个绝对不会乱序的“数据计数器”。
Flags 是命令，Seq/Ack 是数据：[SYN] 表示申请建立连接，[ACK] 表示收到。在三次握手阶段，数据长度（Len=0）均为 0，因为此时还没有开始真正传输文件。&lt;/p&gt;</description></item></channel></rss>