当前位置: 首页 > news >正文

高频面试点:深入理解 TCP 三次握手与四次挥手

在网络通信的世界里,TCP(Transmission Control Protocol,传输控制协议)是确保数据可靠传输的基石。其中,三次握手建立连接、四次挥手断开连接的过程,更是 Java 秋招面试中的高频考点。今天,我们就深入剖析这两个关键过程,结合原理、代码示例与面试真题,帮你吃透知识点 。

一、TCP 三次握手:建立可靠连接

(一)核心原理

TCP 连接的建立基于 三次握手 机制,目的是让客户端和服务器双方确认彼此收发数据的能力,同步初始序列号(ISN),为可靠传输打基础。过程如下:

  1. 第一次握手(客户端 → 服务器):客户端主动打开连接,发送 SYN 报文(SYN=1seq=x ,x 是客户端初始序列号 ),进入 SYN-SENT 状态 。
  2. 第二次握手(服务器 → 客户端):服务器监听端口收到 SYN 报文,回复 SYN+ACK 报文(SYN=1ACK=1seq=y ,ack=x+1 ,y 是服务器初始序列号 ),进入 SYN-RCVD 状态 。
  3. 第三次握手(客户端 → 服务器):客户端收到 SYN+ACK 报文,回复 ACK 报文(ACK=1seq=x+1ack=y+1 ),进入 ESTABLISHED 状态;服务器收到 ACK 报文后,也进入 ESTABLISHED 状态,连接建立完成,双方开始数据传输 

服务器客户端服务器客户端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)进入 ESTABLISHED(连接建立,可传输数据)TCP 三次握手流程

服务器客户端服务器客户端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)进入 ESTABLISHED(连接建立,可传输数据)TCP 三次握手流程

(二)Java 视角的理解(基于 Socket 编程)

在 Java 中,客户端通过 Socket 主动发起连接,服务器通过 ServerSocket 监听端口,底层会自动完成三次握手。示例代码片段:

// 服务器端(简化版)
ServerSocket serverSocket = new ServerSocket(8080); // 监听 8080 端口,等待客户端连接
Socket clientSocket = serverSocket.accept(); // 阻塞,直到三次握手完成,返回 Socket 对象用于通信// 客户端
Socket socket = new Socket("127.0.0.1", 8080); // 主动连接服务器,触发三次握手

当执行 new Socket(...) 时,客户端会先发送 SYN 报文;服务器 accept() 被触发后,回复 SYN+ACK;客户端收到后再回复 ACK,三次握手完成,Socket 才真正可用。

二、TCP 四次挥手:优雅断开连接

(一)核心原理

TCP 连接的断开需要 四次挥手 ,因为 TCP 是全双工通信,双方需要独立关闭各自的读写通道,过程如下:

  1. 第一次挥手(主动关闭方 → 被动关闭方):假设客户端主动关闭,发送 FIN 报文(FIN=1seq=u ),进入 FIN-WAIT-1 状态,表示 “我这边没数据要发了” 。
  2. 第二次挥手(被动关闭方 → 主动关闭方):服务器收到 FIN ,回复 ACK 报文(ACK=1seq=vack=u+1 ),进入 CLOSE-WAIT 状态,告诉客户端 “你的关闭请求已收到,我处理完剩余数据就关闭” ;客户端收到 ACK 后,进入 FIN-WAIT-2 状态,等待服务器真正关闭 。
  3. 第三次挥手(被动关闭方 → 主动关闭方):服务器处理完数据,发送 FIN 报文(FIN=1ACK=1seq=wack=u+1 ),进入 LAST-ACK 状态,表示 “我也没数据发了,准备关闭” 。
  4. 第四次挥手(主动关闭方 → 被动关闭方):客户端收到 FIN ,回复 ACK 报文(ACK=1seq=u+1ack=w+1 ),进入 TIME-WAIT 状态;服务器收到 ACK 后,进入 CLOSED 状态。客户端等待 2MSL(最大报文段生存时间)后,确保服务器能收到 ACK(防止服务器重发 FIN 时丢失),也进入 CLOSED 状态 

服务器(被动关闭)客户端(主动关闭)服务器(被动关闭)客户端(主动关闭)FIN=1, seq=u(进入 FIN-WAIT-1)ACK=1, seq=v, ack=u+1(进入 CLOSE-WAIT)进入 FIN-WAIT-2(收到服务器 ACK 后)FIN=1, ACK=1, seq=w, ack=u+1(进入 LAST-ACK)ACK=1, seq=u+1, ack=w+1(进入 TIME-WAIT)进入 CLOSED(收到客户端 ACK 后)等待 2MSL 后进入 CLOSEDTCP 四次挥手流程

服务器(被动关闭)客户端(主动关闭)服务器(被动关闭)客户端(主动关闭)FIN=1, seq=u(进入 FIN-WAIT-1)ACK=1, seq=v, ack=u+1(进入 CLOSE-WAIT)进入 FIN-WAIT-2(收到服务器 ACK 后)FIN=1, ACK=1, seq=w, ack=u+1(进入 LAST-ACK)ACK=1, seq=u+1, ack=w+1(进入 TIME-WAIT)进入 CLOSED(收到客户端 ACK 后)等待 2MSL 后进入 CLOSEDTCP 四次挥手流程

(二)Java 代码中的体现

基于 Java Socket,当一方调用 socket.close() 时,会触发四次挥手:

// 客户端主动关闭(示例)
Socket socket = new Socket("127.0.0.1", 8080);
// 数据传输...
socket.close(); // 触发第一次挥手(发送 FIN)

服务器端在读取数据时,若检测到客户端关闭(收到 FIN ),会先回复 ACK(第二次挥手),然后处理完自身数据后,调用 socket.close() 触发第三次挥手(发送 FIN );客户端收到服务器 FIN 后回复 ACK(第四次挥手),完成关闭。

三、高频面试题 & 解答

(一)三次握手相关

问题 1:为什么需要三次握手,两次不行吗?
答:

三次握手的核心是 确认双方收发能力 。两次握手时,若客户端第一次 SYN 报文因网络延迟,超时后客户端重发 SYN 并建立连接、传输数据、关闭连接;此时延迟的 SYN 才到达服务器,服务器会认为是新连接,回复 SYN+ACK ,但客户端已关闭,不会处理 ACK,服务器则会一直等待 ACK,造成资源浪费。三次握手通过客户端最后回复的 ACK,让服务器确认 “客户端能收到我的消息”,避免这种无效连接。

问题 2:三次握手过程中,客户端或服务器出现报文丢失,会发生什么?
答:

  • 若客户端 SYN 丢失:客户端会超时重发 SYN,直到收到服务器 SYN+ACK 或达到重试次数。
  • 若服务器 SYN+ACK 丢失:客户端收不到回复,超时重发 SYN;服务器若收到重复 SYN,会重新回复 SYN+ACK 。
  • 若客户端 ACK 丢失:服务器收不到 ACK,会超时重发 SYN+ACK;客户端收到后,再次回复 ACK ,直到服务器确认或超时。

(二)四次挥手相关

问题 1:为什么四次挥手需要四次,不能三次?
答:

因为 TCP 全双工特性,双方都要独立关闭读写。主动关闭方发 FIN 只是说 “我不发数据了”,但还能收数据;被动关闭方收到 FIN 后,要先回复 ACK 确认,然后处理完自己的发送队列,再发 FIN 表示 “我也不发了” 。这两个步骤(回复 ACK 和 发送 FIN )无法合并,所以需要四次挥手。

问题 2:客户端 TIME-WAIT 状态为什么要等待 2MSL
答:

  • 确保最后发送的 ACK 能到达服务器:若服务器没收到 ACK,会重发 FIN,客户端在 2MSL 内可收到并重发 ACK,保证服务器正常关闭。
  • 防止 “旧连接” 干扰新连接:2MSL 可让本连接的所有报文都从网络中消失,新连接不会因残留报文出现混淆。
http://www.dtcms.com/a/317999.html

相关文章:

  • mysql优化策略
  • qt qml实现电话簿 通讯录
  • [FBCTF2019]RCEService
  • apache-tomcat-11.0.9安装及环境变量配置
  • 认识MCP
  • java中普通流stream与并行流parallelStream的比较分析
  • Javascript/ES6+/Typescript重点内容篇——手撕(待总结)
  • 如何定位一个高并发场景下API响应时间从200ms突增到2s的问题
  • 数据结构---二级指针(应用场景)、内核链表、栈(系统栈、实现方式)、队列(实现方式、应用)
  • SQL168 统计作答次数
  • 简单介绍cgroups以及在K8s中的应用
  • DM数据库的安全版本SYSDBA无法修改其他用户密码?
  • 2025年COR SCI2区,船载AUV协同调度优化+海上风电机组水下检测,深度解析+性能实测
  • GPT-oss开源:200万小时淬炼AI Agent专属商用引擎
  • Vi与Vim的主要区别总结
  • Linux systemd 服务管理与 Firewall 防火墙配置
  • 【论文分析】【Agent】SEW: Self-Evolving Agentic Workflows for Automated Code Generatio
  • 从零开始的云计算生活——第三十八天,避坑落井,Docker容器模块
  • 《RedisTemplate 核心操作全解析》
  • 家庭宽带中的服务器如何被外网访问?
  • 无法解析 CentOS 官方镜像源的域名
  • 977.有序数组的平方
  • 什么是回调地址
  • 8、项目管理
  • PI 思维升级 解密电容器的选择与布局策略,带您追求极致平坦的电源阻抗
  • 个人自然人可不可以申请注册商标!
  • 2025国赛数学建模C题详细思路模型代码获取,备战国赛算法解析——决策树
  • Python Day24 多线程编程:核心机制、同步方法与实践案例
  • Lesson 33 Out of the darkness
  • 开疆智能ModbusTCP转Profinet网关连接EPSON机器人配置案例