Win11下Edge浏览器CPU/内存占用高?别急着卸载,试试这3个隐藏设置(附关闭后打不开的终极修复)
2026/5/31 16:48:15
视频看了几百小时还迷糊?关注我,几分钟让你秒懂!
在开发 Spring Boot 应用时,你是否遇到过这些问题:
TIME_WAIT占满端口?这些问题的背后,都藏着一个关键知识点:TCP 的三次握手与四次挥手。
今天,我们就用生活化比喻 + Java 代码演示 + 反例分析,彻底搞懂这个网络核心机制!
想象你打电话给朋友:
拨号 → 对方接听 → 你说“喂,听得见吗?” → 对方回“听得见!”
→ 这才确认双方都能说话(建立连接)。
聊完后,你说“挂了啊” → 对方说“好” → 你挂电话 → 对方也挂
→ 确保双方都同意结束(断开连接)。
TCP 就是这样一种“严谨的通信协议”,它通过三次握手建立连接,四次挥手断开连接,确保数据传输的可靠性。
| 步骤 | 发送方 | 动作 | 标志位 |
|---|---|---|---|
| 1 | 客户端 | 发送 SYN | SYN=1, seq=x |
| 2 | 服务端 | 回复 SYN+ACK | SYN=1, ACK=1, seq=y, ack=x+1 |
| 3 | 客户端 | 发送 ACK | ACK=1, seq=x+1, ack=y+1 |
✅ 此时连接建立成功,双方可开始传输数据。
反例:如果只有两次握手
🔑 三次握手的核心目的:让双方都确认对方的发送和接收能力正常。
TCP 是全双工的,意味着 A→B 和 B→A 可以同时传数据。所以断开时,每个方向都要单独关闭。
| 步骤 | 发送方 | 动作 | 状态变化 |
|---|---|---|---|
| 1 | 客户端 | 发送 FIN | 进入FIN_WAIT_1 |
| 2 | 服务端 | 回复 ACK | 进入CLOSE_WAIT |
| 3 | 服务端 | 发送 FIN(等应用层处理完) | 进入LAST_ACK |
| 4 | 客户端 | 回复 ACK | 进入TIME_WAIT(等待 2MSL 后关闭) |
⚠️ 注意:步骤2和3不能合并!因为服务端可能还有数据要发。
虽然 Spring Boot 默认屏蔽了底层细节,但我们可以通过Socket 编程模拟连接过程。
// TcpServer.java public class TcpServer { public static void main(String[] args) throws IOException { ServerSocket server = new ServerSocket(8080); System.out.println("服务端启动,等待连接..."); Socket client = server.accept(); // ← 这里完成三次握手! System.out.println("客户端已连接"); BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream())); PrintWriter out = new PrintWriter(client.getOutputStream(), true); String msg; while ((msg = in.readLine()) != null) { System.out.println("收到: " + msg); out.println("Echo: " + msg); } // 客户端关闭后,这里会退出循环 client.close(); // ← 触发四次挥手 server.close(); } }// TcpClient.java public class TcpClient { public static void main(String[] args) throws IOException { Socket socket = new Socket("localhost", 8080); // ← 发起三次握手 PrintWriter out = new PrintWriter(socket.getOutputStream(), true); BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); out.println("Hello Server!"); System.out.println("收到回复: " + in.readLine()); socket.close(); // ← 发起四次挥手 } }🔍 运行后,你可以在 Wireshark 或
netstat -an | grep 8080中看到ESTABLISHED、TIME_WAIT等状态!
CLOSE_WAIT// 错误代码:只关输入流,不关 Socket BufferedReader in = new BufferedReader(...); in.close(); // ❌ 这不会触发 FIN! // Socket 一直保持 CLOSE_WAIT,最终耗尽文件描述符!✅ 正确做法:
socket.close(); // 必须关闭整个 Socket!TIME_WAIT占满端口TIME_WAIT(默认 60 秒);✅ 解决方案:
TIME_WAIT,客户端端口多);net.ipv4.tcp_tw_reuse = 1 net.ipv4.tcp_fin_timeout = 30| 问题 | 说明 |
|---|---|
| SYN Flood 攻击 | 攻击者只发 SYN 不完成握手,耗尽服务端资源 → 需开启 SYN Cookie 防护 |
| 2MSL 是什么? | TIME_WAIT等待 2 倍最大段生命周期(约 60 秒),防止旧数据包干扰新连接 |
| HTTP 是短连接? | HTTP/1.1 默认keep-alive,其实是复用 TCP 连接,避免频繁握手 |
| WebSocket 呢? | 建立时用 HTTP Upgrade,之后走 TCP 长连接,挥手仍需四次 |
三次握手(建连): Client --SYN--> Server Client <--SYN+ACK-- Server Client --ACK--> Server → 连接建立! 四次挥手(断连): Client --FIN--> Server Client <--ACK-- Server Client <--FIN-- Server Client --ACK--> Server → 连接关闭!(Client 进入 TIME_WAIT)💡 记住口诀:
“三次握手防失效,四次挥手因双工”
视频看了几百小时还迷糊?关注我,几分钟让你秒懂!