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

TCP 四次挥手

引言:优雅的告别

在网络通信中,建立连接需要三次握手,而终止连接则需要四次挥手。这种设计体现了 TCP 协议的可靠性和完整性原则。本文将用通俗易懂的方式,深入解析四次挥手的原理、状态转换和实际应用,帮助您掌握这一网络通信的核心机制。

一、四次挥手:为何需要四步?

想象两个朋友结束通话的场景:

  1. A 说:“我说完了,要挂电话了”(第一次挥手)
  2. B 回答:“好的,我听到了”(第二次挥手)
  3. B 补充:“我也说完了,要挂了”(第三次挥手)
  4. A 确认:“好的,再见”(第四次挥手)

TCP 四次挥手也是类似的双向确认过程:

主动关闭方 被动关闭方 发送完所有数据 FIN (我要关闭发送通道) 收到关闭请求 ACK (收到你的请求) 处理剩余数据 FIN (我也要关闭发送通道) 收到关闭请求 ACK (收到你的请求) 立即关闭连接 等待2MSL后关闭 主动关闭方 被动关闭方

二、状态转换图解(精准版)

主动关闭方
被动关闭方
close()/shutdown()
收到ACK
收到FIN
2MSL超时
收到FIN
close()/shutdown()
收到ACK
ESTABLISHED
FIN_WAIT_1
FIN_WAIT_2
TIME_WAIT
CLOSED
CLOSE_WAIT
LAST_ACK

关键状态解析:

  1. FIN_WAIT_1:主动方已发送FIN,等待确认
  2. FIN_WAIT_2:收到第一次ACK,等待对方FIN
  3. CLOSE_WAIT:被动方收到FIN,准备关闭
  4. LAST_ACK:被动方发送FIN,等待最后确认
  5. TIME_WAIT:主动方确保对方收到ACK(等待2MSL)

MSL(Maximum Segment Lifetime):报文最大生存时间,通常30-120秒

三、核心函数与代码示例

主动关闭方(客户端):

// 发送完数据后关闭连接
close(sockfd); // 或者优雅关闭(推荐)
shutdown(sockfd, SHUT_WR); // 先关闭写通道
// 继续读取剩余数据...
close(sockfd);             // 完全关闭

被动关闭方(服务端):

while ((bytes = read(sockfd, buffer, BUFFER_SIZE)) > 0) {// 处理数据...
}if (bytes == 0) { // 收到FIN(EOF)close(sockfd); // 关闭连接触发第三次挥手
}

四、为什么需要TIME_WAIT状态?

TIME_WAIT 是面试必问知识点!它有两个关键作用:

  1. 确保最后一个ACK到达
    如果ACK丢失,被动方会重发FIN,TIME_WAIT状态能重新发送ACK

  2. 防止旧连接数据混淆
    等待2MSL确保网络中属于该连接的报文全部消失,避免影响新连接

查看TIME_WAIT连接:

netstat -n | grep TIME_WAIT
ss -tan | grep TIME-WAIT

五、常见问题与解决方案

问题1:服务器出现大量CLOSE_WAIT

  • 原因:应用未调用close()
  • 解决:检查代码资源释放逻辑,确保每个socket都被关闭

问题2:TIME_WAIT过多导致端口耗尽

  • 优化方案
    # 启用TIME_WAIT重用(Linux)
    sysctl -w net.ipv4.tcp_tw_reuse=1# 减少FIN超时时间
    sysctl -w net.ipv4.tcp_fin_timeout=30
    

问题3:连接卡在FIN_WAIT_2

  • 原因:被动方未发送FIN
  • 解决:检查被动方应用是否正常关闭连接

六、实际抓包分析(Wireshark示例)

No.  Time     Source       Destination  Protocol Info
1    0.000   192.168.1.1  192.168.1.2  TCP      [FIN], Seq=100
2    0.001   192.168.1.2  192.168.1.1  TCP      [ACK], Ack=101
3    1.002   192.168.1.2  192.168.1.1  TCP      [FIN], Seq=300
4    1.002   192.168.1.1  192.168.1.2  TCP      [ACK], Ack=301

关键点:

  • FIN和ACK标志位的变化
  • 序列号(Seq)和确认号(Ack)的连续性
  • 时间间隔(可能包含数据处理时间)

总结:四次挥手的核心价值

  1. 可靠性:通过四次交互确保双方都完成数据发送
  2. 有序性:状态机管理确保关闭过程有序进行
  3. 安全性:TIME_WAIT防止报文混淆和丢失
  4. 灵活性:支持半关闭(shutdown)等高级用法

最佳实践

  • 服务端使用连接池减少握手/挥手开销
  • 客户端使用优雅关闭(shutdown)避免数据丢失
  • 监控关键状态(CLOSE_WAIT/TIME_WAIT)预防资源泄漏

理解四次挥手不仅有助于解决网络问题,更能帮助开发者设计高性能、高可靠的网络应用。当你下次看到TIME_WAIT时,请记得这是TCP为保障可靠性所做的最后努力。

http://www.lryc.cn/news/2397032.html

相关文章:

  • MSTNet:用于糖尿病视网膜病变分类的多尺度空间感知 Transformer 与多实例学习方法|文献速递-深度学习医疗AI最新文献
  • docker运行程序Killed异常排查
  • 【数学 逆序对 构造】P12386 [蓝桥杯 2023 省 Python B] 混乱的数组|普及+
  • Excel 批量下载PDF、批量下载考勤图片——仙盟创梦IDE
  • PCIe-Error Detection(一)
  • 向量空间的练习题目
  • Leetcode 2123. 使矩阵中的 1 互不相邻的最小操作数
  • MySQL高可用集群
  • day14 leetcode-hot100-27(链表6)
  • YOLOv5 :训练自己的数据集
  • flutter项目迁移空安全
  • vue element日期范围选择器只能选择指定天数内的
  • 从 AMQP 到 RabbitMQ:核心组件设计与工作原理(二)
  • MySql(十二)
  • 51c视觉~3D~合集3
  • windows11安装编译QtMvvm
  • 【2025年电工杯数学建模竞赛A题】光伏电站发电功率日前预测问题+完整思路+paper+源码
  • OpenCv高阶(十九)——dlib关键点定位
  • BUUCTF之[ACTF2020 新生赛]BackupFile
  • 头歌之动手学人工智能-Pytorch 之autograd
  • OIer常用的软件
  • Centos7.x内网环境Jenkins前端打包环境配置
  • Kafka集成Flume/Spark/Flink(大数据)/SpringBoot
  • Scratch节日 | 拯救屈原 | 端午节
  • rabbitmq Direct交换机简介
  • Git实战--基于已有分支克隆进行项目开发的完整流程
  • MapReduce(期末速成版)
  • 鸿蒙OSUniApp 移动端直播流播放实战:打造符合鸿蒙设计风格的播放器#三方框架 #Uniapp
  • C3、C2f、C3K2、C2PSA的具体结构
  • 2_MCU开发环境搭建-配置MDK兼容Keil4和C51