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

TCP 三次握手与四次挥手详解

一、TCP 连接建立(三次握手)

Client Server CLOSED → SYN_SENT SYN=1, seq=x (SYN包) CLOSED → SYN_RCVD SYN=1, ACK=1, seq=y, ack=x+1 (SYN-ACK包) SYN_SENT → ESTABLISHED ACK=1, seq=x+1, ack=y+1 (ACK包) SYN_RCVD → ESTABLISHED Client Server

详细过程:

  1. 第一次握手(SYN)

    • 客户端发送 SYN=1 标志(同步序列号)
    • 随机生成初始序列号 seq=x
    • 进入 SYN_SENT 状态
  2. 第二次握手(SYN-ACK)

    • 服务器收到 SYN 后,发送 SYN=1 和 ACK=1
    • 确认号 ack=x+1(期待收到 x+1)
    • 随机生成自己的序列号 seq=y
    • 进入 SYN_RCVD 状态
  3. 第三次握手(ACK)

    • 客户端确认收到 SYN-ACK
    • 发送 ACK=1,ack=y+1,seq=x+1
    • 双方进入 ESTABLISHED 状态

关键点:

  • 为什么需要三次?
    防止历史重复连接初始化导致的资源浪费(两次无法确认客户端接收能力)
  • 序列号作用
    解决网络包乱序、重复问题,保证可靠性

二、TCP 连接释放(四次挥手)

Client Server ESTABLISHED → FIN_WAIT_1 FIN=1, seq=u (FIN包) ESTABLISHED → CLOSE_WAIT ACK=1, ack=u+1 (ACK包) FIN_WAIT_1 → FIN_WAIT_2 FIN=1, seq=v, ack=u+1 (FIN包) CLOSE_WAIT → LAST_ACK ACK=1, ack=v+1, seq=u+1 (ACK包) FIN_WAIT_2 → TIME_WAIT → CLOSED LAST_ACK → CLOSED Client Server

详细过程:

  1. 第一次挥手(FIN)

    • 主动方发送 FIN=1,seq=u
    • 进入 FIN_WAIT_1 状态
  2. 第二次挥手(ACK)

    • 被动方发送 ACK=1,ack=u+1
    • 进入 CLOSE_WAIT 状态
    • 主动方收到后进入 FIN_WAIT_2
  3. 第三次挥手(FIN)

    • 被动方处理完数据后,发送 FIN=1,seq=v
    • 进入 LAST_ACK 状态
  4. 第四次挥手(ACK)

    • 主动方发送 ACK=1,ack=v+1
    • 进入 TIME_WAIT 状态(等待 2MSL)
    • 被动方收到后关闭连接

关键点:

  • 为什么需要四次?
    TCP 是全双工的,必须分别关闭两个方向的数据流
  • TIME_WAIT 状态
    • 等待 2MSL(Maximum Segment Lifetime,默认 60s)
    • 确保最后一个 ACK 到达对方
    • 让网络中残留的旧报文失效

三、状态机转换图

连接建立:

CLOSED → SYN_SENT → ESTABLISHED
CLOSED → SYN_RCVD → ESTABLISHED

连接释放:

ESTABLISHED → FIN_WAIT_1 → FIN_WAIT_2 → TIME_WAIT → CLOSED
ESTABLISHED → CLOSE_WAIT → LAST_ACK → CLOSED

四、常见问题

Q1:为什么不能用两次握手建立连接?

  • 可能造成历史重复连接占用服务器资源
  • 无法确认客户端的接收能力是否正常

Q2:TIME_WAIT 状态过多的危害?

  • 占用端口资源(高并发时可能耗尽端口)
  • 解决方案:
    • 调整 net.ipv4.tcp_tw_reuse 参数
    • 使用 SO_REUSEADDR 套接字选项

Q3:如果最后一次 ACK 丢失会怎样?

  • 被动方会重传 FIN 包
  • 主动方在 TIME_WAIT 期间能响应这些重传

五、Wireshark 抓包示例

三次握手:

1. [SYN] Seq=0
2. [SYN, ACK] Seq=0, Ack=1
3. [ACK] Seq=1, Ack=1

四次挥手:

1. [FIN, ACK] Seq=1, Ack=1
2. [ACK] Seq=1, Ack=2
3. [FIN, ACK] Seq=1, Ack=2
4. [ACK] Seq=2, Ack=2

六、编程实现(Python 伪代码)

# 服务端
def server():s = socket.socket()s.bind(('0.0.0.0', 80))s.listen()conn, addr = s.accept()  # 完成三次握手conn.close()  # 触发四次挥手# 客户端
def client():s = socket.socket()s.connect(('server', 80))  # 发起三次握手s.close()  # 发起四次挥手
http://www.lryc.cn/news/579477.html

相关文章:

  • MyBatis 之基础概念与框架原理详解
  • RabbitMQ 通过HTTP API删除队列命令
  • 【如何判断Linux系统是Ubuntu还是CentOS】
  • Centrifugo 深度解析:构建高性能实时应用的开源引擎
  • 记忆翻牌记忆力小游戏流量主微信小程序开源
  • 网创vip课程视频教程、付费网络课程以及网赚培训,学习引流、建站、赚钱。8个T的全套课程
  • 【2.3 漫画SpringSecurity - 守护应用安全的钢铁卫士】
  • ATE FT ChangeKit学习总结-20250630
  • Easy-excel监听器中对批量上传的工单做错误收集
  • Redisson使用示例
  • 请求未达服务端?iOS端HTTPS链路异常的多工具抓包排查记录
  • 【Bug Recod】更新中...
  • Day50
  • 一文详解Character AI:实用指南+ ChatGPT、Gemini对比分析
  • contenteditable网页富文本编辑无法选中图片
  • Swift 的基础设计哲学是 “通过模块化组合实现安全与效率的平衡“,就像用标准化工业零件建造摩天大楼
  • 一台香港原生ip站群服务器多少钱?
  • 如何在Ubuntu上检查MySQL是否启动并放开3306端口
  • C++笔记-位图和布隆过滤器
  • P1155 [NOIP 2008 提高组] 双栈排序
  • 李宏毅机器学习笔记——梯度下降法
  • 映射阿里云OSS(对象存储服务)
  • 百度文心智能体平台x小米应用商店:联手打造行业首个智能体与应用市场跨端分发模式
  • webrtc-streamer视频流播放(rstp协议h264笔记)
  • KDD 2025 | 地理定位中的群体智能:一个多智能体大型视觉语言模型协同框架
  • Go应用容器化完全指南:构建最小化安全镜像的终极实践
  • I/O 线程 7.3
  • VTK中自定义双组分输入最大值滤波
  • 基于spark的北京房价数据分析及价格预测
  • npm 命令入门指南(前端小白版)