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

深度解析 TCP 三次握手与四次挥手:从原理到 HTTP/HTTPS 的应用

TCP 的三次握手和四次挥手是网络通信的基石,无论是 HTTP 还是 HTTPS,它们都依赖 TCP 提供可靠的传输层服务。本文将用万字篇幅,结合 Mermaid 图表和代码示例,深入讲解 TCP 三次握手、四次挥手的原理、过程、状态变化,以及它们在 HTTP 和 HTTPS 中的应用场景。无论你是网络新手还是想深入理解 TCP 的开发者,这篇文章都会带你全面掌握这些核心机制!

1. TCP 协议概述

TCP(Transmission Control Protocol,传输控制协议)是互联网协议栈中的传输层协议,旨在提供可靠的、面向连接的、字节流传输服务。它确保数据包按序到达、无丢失、无重复,广泛应用于 HTTP、HTTPS、FTP 等协议。

TCP 的核心特性

  • 可靠性:通过序列号、确认机制和重传机制保证数据完整性。
  • 面向连接:通信前通过三次握手建立连接,通信后通过四次挥手断开连接。
  • 流量控制:通过滑动窗口避免发送方过载接收方。
  • 拥塞控制:通过算法(如慢启动、拥塞避免)适应网络状况。

TCP 在协议栈中的位置

应用层: HTTP/HTTPS
传输层: TCP
网络层: IP
数据链路层
物理层

图表说明

  • HTTP/HTTPS 运行在应用层,依赖 TCP 提供可靠传输。
  • TCP 封装数据为段(Segment),交给 IP 层传输。

2. TCP 三次握手详解

三次握手(Three-Way Handshake)是 TCP 建立连接的过程,确保双方准备好通信并协商初始序列号。它包含三次数据包交互,涉及客户端和服务器之间的状态转换。

2.1 三次握手的流程

三次握手的目的是建立可靠的连接,确保双方都能发送和接收数据,同时初始化序列号以跟踪数据传输。

三次握手流程图

客户端服务器SYN (seq=x)服务器: LISTEN ->> SYN_RECEIVEDSYN+ACK (seq=y, ack=x+1)客户端: SYN_SENT ->> ESTABLISHEDACK (ack=y+1)服务器: SYN_RECEIVED ->> ESTABLISHED数据传输客户端服务器

流程详解

  1. 第一次握手(SYN)

    • 客户端发送 SYN(Synchronize)包,包含初始序列号 seq=x
    • 客户端进入 SYN_SENT 状态,等待服务器响应。
    • 目的:通知服务器客户端希望建立连接,并提供初始序列号。
  2. 第二次握手(SYN+ACK)

    • 服务器收到 SYN 包,回复 SYN+ACK 包,包含自己的初始序列号 seq=y 和确认号 ack=x+1
    • 服务器从 LISTEN 状态进入 SYN_RECEIVED 状态。
    • 目的:确认收到客户端的 SYN,并表明服务器也准备好通信。
  3. 第三次握手(ACK)

    • 客户端收到 SYN+ACK 包,回复 ACK 包,包含确认号 ack=y+1
    • 客户端进入 ESTABLISHED 状态,服务器收到 ACK 后也进入 ESTABLISHED 状态。
    • 目的:确认双方都已准备好,连接正式建立。

状态转换图

服务器启动
客户端发送 SYN
收到 SYN,发送 SYN+ACK
收到 SYN+ACK,发送 ACK
收到 ACK
CLOSED
LISTEN
SYN_SENT
SYN_RECEIVED
ESTABLISHED
style
#FF6384
#36A2EB
#FFCE56
#4BC0C0
#36A2EB

关键点

  • 为什么需要三次握手?
    • 确保双方都能发送和接收数据(双向通信)。
    • 同步初始序列号,避免旧连接干扰。
    • 防止因网络延迟导致的错误连接(如重复的 SYN 包)。
  • 序列号的作用
    • TCP 使用序列号(Sequence Number)跟踪数据段的顺序。
    • 确认号(Acknowledgment Number)表示期望接收的下一个字节。

2.2 三次握手的代码模拟

以下是使用 Node.js 的简单代码模拟三次握手的概念(实际 TCP 握手由操作系统内核处理):

const net = require('net');// 服务器端
const server = net.createServer((socket) => {console.log('客户端发起连接 (SYN)');socket.write('SYN+ACK', () => {console.log('服务器响应 SYN+ACK');});socket.on('data', (data) => {if (data.toString() === 'ACK') {console.log('客户端确认 ACK,连接建立');socket.write('欢迎开始数据传输!');}});
});server.listen(8080, () => {console.log('服务器监听中 (LISTEN)');
});// 客户端
const client = new net.Socket();
client.connect(8080, '127.0.0.1', () => {console.log('客户端发送 SYN');client.write('SYN');
});client.on('data', (data) => {if (data.toString() === 'SYN+ACK') {console.log('收到 SYN+ACK,发送 ACK');client.write('ACK');} else {console.log('收到数据:', data.toString());}
});

运行结果

  1. 服务器启动,进入 LISTEN 状态。
  2. 客户端发送 SYN,模拟第一次握手。
  3. 服务器响应 SYN+ACK,模拟第二次握手。
  4. 客户端发送 ACK,模拟第三次握手,连接建立。

优化建议

  • 在实际应用中,TCP 握手由操作系统内核完成,开发者无需手动实现。
  • 确保服务器监听端口未被占用,避免握手失败。

3. TCP 四次挥手详解

四次挥手(Four-Way Handshake)是 TCP 断开连接的过程,确保双方有序关闭连接,避免数据丢失。

3.1 四次挥手的流程

四次挥手的目的是安全关闭连接,确保双方都完成数据发送并确认对方已收到。

四次挥手流程图

客户端服务器FIN (seq=x)服务器: ESTABLISHED ->> CLOSE_WAITACK (ack=x+1)客户端: FIN_WAIT_1 ->> FIN_WAIT_2FIN (seq=y)客户端: FIN_WAIT_2 ->> TIME_WAITACK (ack=y+1)服务器: CLOSE_WAIT ->> CLOSED客户端: TIME_WAIT ->> CLOSED客户端服务器

流程详解

  1. 第一次挥手(FIN)

    • 客户端(或服务器)发送 FIN(Finish)包,包含序列号 seq=x,表示不再发送数据。
    • 客户端进入 FIN_WAIT_1 状态。
    • 目的:通知对方客户端希望关闭连接。
  2. 第二次挥手(ACK)

    • 服务器收到 FIN,回复 ACK 包,包含确认号 ack=x+1
    • 服务器进入 CLOSE_WAIT 状态,客户端进入 FIN_WAIT_2 状态。
    • 目的:确认收到客户端的 FIN,允许服务器继续发送未完成的数据。
  3. 第三次挥手(FIN)

    • 服务器发送完剩余数据后,发送 FIN 包,包含序列号 seq=y
    • 服务器进入 LAST_ACK 状态。
    • 目的:通知客户端服务器也准备关闭连接。
  4. 第四次挥手(ACK)

    • 客户端收到 FIN,回复 ACK 包,包含确认号 ack=y+1
    • 客户端进入 TIME_WAIT 状态,等待一段时间(通常 2MSL,最大段生存时间)后进入 CLOSED 状态。
    • 服务器收到 ACK 后进入 CLOSED 状态。
    • 目的:确认双方都完成关闭,避免残留数据包干扰。

状态转换图

客户端发送 FIN
收到 ACK
收到 FIN,发送 ACK
发送 FIN
收到 FIN,发送 ACK
收到 ACK
等待 2MSL
ESTABLISHED
FIN_WAIT_1
FIN_WAIT_2
CLOSE_WAIT
LAST_ACK
TIME_WAIT
CLOSED
style
#36A2EB
#FFCE56
#4BC0C0
#FF6384
#36A2EB
#FFCE56
#4BC0C0

关键点

  • 为什么需要四次挥手?
    • TCP 是全双工通信,双方需要分别关闭发送方向的连接。
    • 四次挥手确保双方都完成数据发送并确认。
  • TIME_WAIT 的作用
    • 防止旧连接的数据包干扰新连接。
    • 确保服务器收到最后的 ACK,避免服务器无限等待。
  • 2MSL 等待时间
    • MSL(Maximum Segment Lifetime)是数据包在网络中的最大存活时间。
    • 2MSL 确保网络中残留的数据包失效。

3.2 四次挥手的代码模拟

以下是 Node.js 模拟四次挥手的概念(简化版):

const net = require('net');// 服务器
const server = net.createServer((socket) => {socket.on('data', (data) => {if (data.toString() === 'FIN') {console.log('收到客户端 FIN,发送 ACK');socket.write('ACK');setTimeout(() => {console.log('服务器发送 FIN');socket.write('FIN');}, 1000); // 模拟服务器处理剩余数据} else if (data.toString() === 'ACK') {console.log('收到客户端 ACK,服务器关闭连接');socket.end();}});
});server.listen(8080, () => {console.log('服务器监听中');
});// 客户端
const client = new net.Socket();
client.connect(8080, '127.0.0.1', () => {console.log('客户端发送 FIN');client.write('FIN');
});client.on('data', (data) => {if (data.toString() === 'ACK') {console.log('收到服务器 ACK');} else if (data.toString() === 'FIN') {console.log('收到服务器 FIN,发送 ACK');client.write('ACK');setTimeout(() => {console.log('客户端进入 TIME_WAIT,关闭连接');client.end();}, 2000); // 模拟 2MSL 等待}
});

运行结果

  1. 客户端发送 FIN,模拟第一次挥手。
  2. 服务器响应 ACK,模拟第二次挥手。
  3. 服务器发送 FIN,模拟第三次挥手。
  4. 客户端响应 ACK,进入 TIME_WAIT,模拟第四次挥手。

4. TCP 在 HTTP 和 HTTPS 中的应用

HTTP 和 HTTPS 都基于 TCP 提供可靠传输,下面分析它们如何利用三次握手和四次挥手。

4.1 HTTP 与 TCP

HTTP(HyperText Transfer Protocol)是应用层协议,运行在 TCP 之上,用于传输网页内容。

HTTP 请求流程图

客户端服务器三次握手SYNSYN+ACKACKHTTP 请求GET /index.html200 OK, HTML 数据四次挥手FINACKFINACK客户端服务器

关键点

  • 短连接(HTTP/1.0):每次请求都需要新的 TCP 连接(三次握手 + 四次挥手),开销较大。
  • 长连接(HTTP/1.1):通过 Connection: keep-alive,在同一 TCP 连接上复用多个请求,减少握手开销。

代码示例(HTTP 长连接)

GET /index.html HTTP/1.1
Host: example.com
Connection: keep-alive

优化建议

  • 使用 HTTP/1.1 或 HTTP/2 的长连接减少 TCP 握手次数。
  • 合并请求(如 CSS Sprites)减少连接需求。

4.2 HTTPS 与 TCP

HTTPS(HTTP Secure)在 HTTP 基础上通过 TLS/SSL 提供加密通信,但仍依赖 TCP。

HTTPS 连接流程图

客户端服务器三次握手SYNSYN+ACKACKTLS 握手Client HelloServer Hello, CertificateKey Exchange, Change Cipher SpecChange Cipher SpecHTTP 请求GET /index.html (加密)200 OK, HTML 数据 (加密)四次挥手FINACKFINACK客户端服务器

关键点

  • TLS 握手:在 TCP 三次握手后,HTTPS 额外进行 TLS 握手,协商加密算法和密钥。
  • 性能开销:TLS 握手增加延迟,但通过会话复用(Session Resumption)可优化。
  • 四次挥手:与 HTTP 相同,HTTPS 在数据传输完成后通过四次挥手关闭连接。

优化建议

  • 使用 TLS 1.3,减少握手轮次。
  • 启用会话复用(如 Session Tickets)减少 TLS 握手开销。
  • 使用 HSTS(HTTP Strict Transport Security)强制 HTTPS。

5. TCP 常见问题与优化

5.1 三次握手的问题

  • SYN 洪水攻击

    • 攻击者发送大量 SYN 包但不完成第三次握手,导致服务器资源耗尽。
    • 防御:使用 SYN Cookie,限制半连接队列大小。
  • 延迟影响

    • 三次握手增加初次连接的延迟,特别是在高延迟网络中。
    • 优化:使用 TCP Fast Open(TFO),在第一次握手时携带数据。

5.2 四次挥手的问题

  • TIME_WAIT 堆积

    • 客户端在 TIME_WAIT 状态等待 2MSL,可能导致端口耗尽。
    • 优化:调整系统参数(如 tcp_tw_reuse),或使用长连接减少挥手。
  • 半关闭状态

    • 服务器在 CLOSE_WAIT 状态停留时间过长,可能因未及时发送 FIN。
    • 优化:确保服务器及时关闭连接。

问题与优化对比图

问题
SYN 洪水攻击
TIME_WAIT 堆积
优化
SYN Cookie
TCP Fast Open
长连接

6. 完整流程总览

以下是 TCP 三次握手、四次挥手以及 HTTP/HTTPS 应用的完整流程图,清晰展示整个通信过程。

完整通信流程图

sequenceDiagramparticipant C as 客户端participant S as 服务器Note over C,S: 三次握手C->>S: SYN (seq=x)S->>C: SYN+ACK (seq=y, ack=x+1)C->>S: ACK (ack=y+1)Note over C,S: HTTPS: TLS 握手C->>S: Client HelloS->>C: Server Hello, CertificateC->>S: Key Exchange, Change Cipher SpecS->>C: Change Cipher SpecNote over C,S: HTTP/HTTPS 数据传输C->>S: GET /index.html (加密)S->>C: 200 OK, HTML 数据 (加密)Note over C,S: 四次挥手C->>S: FIN (seq=x)S->>C: ACK (ack=x+1)S->>C: FIN (seq=y)C->>S: ACK (ack=y+1)style C fill:#36A2EBstyle S fill:#FFCE56

图表说明

  • 三次握手:建立 TCP 连接,初始化序列号。
  • TLS 握手:HTTPS 额外协商加密参数。
  • 数据传输:HTTP/HTTPS 请求和响应。
  • 四次挥手:有序关闭连接,确保数据完整性。

7. 总结

TCP 的三次握手和四次挥手是网络通信的基石,确保了可靠的连接建立和关闭。HTTP 和 HTTPS 依赖 TCP 提供稳定传输,HTTPS 额外通过 TLS 握手实现加密。三次握手同步序列号,四次挥手确保数据发送完成,结合 Mermaid 图表和代码示例,我们清晰地展示了这些机制的原理和应用场景。

通过优化(如长连接、TLS 1.3、TCP Fast Open),我们可以显著提升网络性能。希望这篇文章能让你深入理解 TCP 握手与挥手机制,并在开发中更高效地应用 HTTP 和 HTTPS!

点个收藏,关注前端结城,一起用代码点亮前端世界!🚀

http://www.xdnf.cn/news/17167.html

相关文章:

  • 【AI论文】iLRM:一种迭代式大型3D重建模型
  • Vue3视频播放组件自定义封装、控制是否自动播放、全屏小屏控制、loading加载、静音播放等样式完全自定义控制,代码复制即用
  • JAVA学习笔记 自增与自减的使用-006
  • uniapp转app时,cover-view的坑
  • Chisel芯片开发入门系列 -- 18. CPU芯片开发和解释8(流水线架构的代码级理解)
  • 基于k8s环境下的pulsar常用命令(下)
  • 创维智能融合终端SK-M424_S905L3芯片_2+8G_安卓9_线刷固件包
  • 计算机网络:目的网络在路由表项中的作用
  • 如何通过 5 种方式将照片从 iPad 传输到电脑
  • MongoDB学习专题(一)介绍安装基本操作
  • 电路基础相关知识
  • 【轮播图】H5端轮播图、横向滑动、划屏效果实现方案——Vue3+CSS position
  • Python爬虫09_Requests用bs4进行数据解析
  • Java、Android及计算机基础面试题总结
  • ubuntu-server安装
  • 外协采购订单的价格差异科目没有产生差异科目问题
  • MongoDB学习专题(二)核心操作
  • 使用buildx构建镜像
  • 蓝桥杯常用java API
  • 东北大学“进化论”赋能具身导航!SE-VLN:基于多模态大模型的自进化视觉语言导航框架
  • wps创建编辑excel customHeight 属性不是标准 Excel Open XML导致比对异常
  • 【qt5_study】2.使用Qt Designer构造UI界面(信号与槽)
  • PHP实战代码解析与应用分享:用户管理、日志,配置管理与文件操作全解析
  • 《C++》继承完全指南:从入门到精通
  • 基于 Spring Boot 的小区人脸识别与出入记录管理系统实现
  • mac安装pycharm
  • 【Dify学习笔记】:保留原所有数据,升级Dify版本
  • Android 中几种常用布局的优缺点
  • Leetcode 13 java
  • Django中的转发与重定向详解