TCP三次握手和四次挥手

详细解析TCP三次握手和四次挥手过程,通过快递员送货的生动例子,阐述连接的建立和断开机制及其背后的原理。

目录

  1. TCP协议简介
  2. 三次握手过程
  3. 四次挥手过程
  4. 技术细节解析
  5. 实际应用场景
  6. 安全性考虑

TCP协议简介

TCP(传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。它具有以下特点:

面向连接:通信前需要建立连接(三次握手),通信结束后需要断开连接(四次挥手) • 可靠传输:使用确认机制和重传机制确保数据不丢失 • 流量控制:通过滑动窗口机制控制发送速率 • 拥塞控制:避免网络拥塞,动态调整传输速率


📦 三次握手过程——例子:快递员确认收货地址

假设你的浏览器(Chrome)是寄件人,服务器(Apache)是收件人,TCP协议(运输层)是快递公司,三次握手就像快递员上门确认地址的过程:

1. 第一次握手(浏览器→服务器)

动作: • 浏览器发送一个SYN=1的包裹(SYN是同步序列号请求),并生成随机序号seq=1000 • 快递员(TCP)说:“您好,我是快递员,Chrome想给Apache寄包裹,您能收吗?” • 状态变化: • 客户端状态:CLOSED → SYN_SENT • 服务端状态:LISTEN

2. 第二次握手(服务器→浏览器)

动作: • 服务器收到SYN后,回复SYN=1 + ACK=1,序号seq=2000,确认号ack=1001 • 快递员反馈:“Apache确认能收件,请把包裹按编号1001开始发给我!” • 状态变化: • 服务端状态:LISTEN → SYN_RECEIVED • 技术点: • ACK=1表示确认收到第一次握手 • ack=1001表示"我期待收到下一个编号是1001的数据" • 确认号计算规则:收到的序号+1

3. 第三次握手(浏览器→服务器)

动作: • 浏览器发送ACK=1,序号seq=1001,确认号ack=2001 • 快递员说:“好的,我会按您的要求开始寄送!” • 状态变化: • 客户端状态:SYN_SENT → ESTABLISHED • 服务端状态:SYN_RECEIVED → ESTABLISHED

💡 为什么必须三次?

防止历史连接干扰:如果第一次握手的包裹卡在路由器(N1/N2)后又重复发送,服务器能通过第三次握手判断是否为过期请求 • 确保双方同步:通过三次握手,双方都能确认对方的发送和接收能力 • 避免资源浪费:防止已失效的连接请求报文突然又传送到服务端,造成错误


四次挥手过程——例子:快递员确认包裹已全部送达

当数据传输完毕,TCP需要安全断开连接,就像快递员要确认双方都没有包裹需要寄送了:

1. 第一次挥手(浏览器→服务器)

动作: • 浏览器发送FIN=1(FIN是结束标志),序号seq=5000 • 快递员说:“Chrome的包裹都寄完了,准备收工啦!” • 状态变化: • 客户端状态:ESTABLISHED → FIN_WAIT_1

2. 第二次挥手(服务器→浏览器)

动作: • 服务器回复ACK=1,确认号ack=5001 • 快递员反馈:“好的,我收到你的收工通知了,但等我确认Apache还有没有包裹要寄给你” • 状态变化: • 服务端状态:ESTABLISHED → CLOSE_WAIT • 客户端状态:FIN_WAIT_1 → FIN_WAIT_2

3. 第三次挥手(服务器→浏览器)

动作: • 服务器发送FIN=1,序号seq=8000 • 快递员说:“Apache这边也没有包裹要寄了,可以收工!” • 状态变化: • 服务端状态:CLOSE_WAIT → LAST_ACK

4. 第四次挥手(浏览器→服务器)

动作: • 浏览器回复ACK=1,确认号ack=8001 • 快递员确认:“双方都确认完毕,连接正式关闭!” • 状态变化: • 客户端状态:FIN_WAIT_2 → TIME_WAIT → CLOSED • 服务端状态:LAST_ACK → CLOSED

💡 为什么挥手要四次?

双向关闭原则:TCP是全双工通信,每个方向都需要单独关闭 • 第一次挥手:客户端关闭发送通道 • 第二次挥手:服务端确认客户端的关闭请求 • 第三次挥手:服务端关闭发送通道 • 第四次挥手:客户端确认服务端的关闭请求 • 数据完整性保证:确保双方的数据都能完整传输,不会因为一方提前关闭而丢失数据


🔧 技术细节解析

TCP标志位说明

SYN(同步序列号):用于建立连接时同步序列号 • ACK(确认标志):表示确认号字段有效 • FIN(结束标志):用于释放连接 • RST(重置连接):用于异常终止连接 • PSH(推送标志):接收方应尽快将这个报文段交给应用层 • URG(紧急标志):表示紧急指针字段有效

序列号与确认号

序列号(seq): • 用于标识从TCP源端向目的端发送的字节流 • 初始序列号(ISN)是随机生成的 • 确认号(ack): • 期望收到对方下一个报文段的第一个数据字节的序号 • 计算方式:收到的序列号 + 1


🌐 实际应用场景

1. 网页浏览

场景描述: • 打开网页时自动完成三次握手 • 数据传输过程中保持连接 • 关闭标签页时触发四次挥手 • 注意事项: • 现代浏览器通常使用HTTP长连接(Keep-Alive) • 一个TCP连接可以复用于多个HTTP请求

2. 文件下载

特点: • 建立连接后持续传输大量数据 • 支持断点续传(基于序列号机制) • 优化建议: • 适当增大TCP窗口大小 • 启用TCP快速重传机制

3. 实时通信

应用场景: • 即时通讯 • 在线游戏 • 视频会议 • 性能考虑: • 需要低延迟 • 可能需要配置TCP_NODELAY选项


🛡️ 安全性考虑

1. SYN洪泛攻击

攻击原理: • 攻击者发送大量SYN请求但不完成三次握手 • 服务器为每个请求分配资源,最终耗尽资源 • 防护措施: • 启用SYN Cookie • 增大半连接队列 • 设置合理的超时时间

2. TCP重置攻击

攻击原理: • 攻击者伪造RST包中断正常连接 • 防护措施: • 启用TCP MD5认证 • 使用IPSec保护TCP连接

3. 连接耗尽攻击

攻击原理: • 建立大量TCP连接但不释放 • 防护措施: • 限制单IP的最大连接数 • 启用连接超时机制


🔍 常见问题与解决方案

1. 连接建立失败

可能原因: • 网络不通 • 服务端端口未开放 • 防火墙拦截 • 解决方案: • 检查网络连通性 • 确认服务状态 • 检查防火墙规则

2. 连接无法释放

可能原因: • TIME_WAIT状态积累 • 程序未正确关闭连接 • 解决方案: • 调整TCP参数(tcp_tw_reuse) • 优化程序代码,确保正确关闭连接

3. 性能问题

表现: • 连接建立慢 • 数据传输延迟大 • 优化方案: • 使用TCP Fast Open • 调整TCP缓冲区大小 • 优化网络路由


📚 延伸阅读

  1. TCP状态转换
  2. TCP流量控制
  3. TCP拥塞控制
  4. TCP keepalive机制
  5. TCP安全加固最佳实践