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

TCP为什么需要四次挥手?

tcp为什么需要四次挥手?

答案有两个:

1.将发送fin包的权限交给被动断开方的应用层去处理,也就是让程序员处理

2.接第一个答案,应用层有了发送fin的权限,可以在发送fin前继续向对端发送消息

为了搞清楚这个问题,我们先要了解四次挥手的过程:

在这里插入图片描述

1.注意事项

  • tcp四次挥手过程中没有客户端和服务端的概念,只有主动方和被动方之分
  • 所有的ack包不会自动重传,如果ack包超时或丢失,通过对端重发fin来解决

2.四次挥手的开始条件

  • 主动断开方调用shutdown,关闭读端
  • 主动断开方调用shutdown,关闭写端
  • 主动断开方调用close,关闭读端和写端
  • 主动断开方程序崩溃,关闭双端,协议栈发送RST包

3.第一次挥手详解

  • 主动断开方触发四个条件之一,协议栈会在内核态发送fin包
  • 如果超时时间内未收到ack,协议栈会重发fin
  • 如果由于程序崩溃,协议栈只发送一次RST包,进入快速关闭流程

4.第二次挥手详解

  • 主动关闭方发送fin,向被动方的读缓冲区写入eof结束符,被动方收到可读事件,read返回值为0
  • 被动断开方根据read返回值0判断对方请求关闭连接,但并不知道对方有没有关闭读端
  • 被动断开方可以选择继续发送数据,如果对方关闭读端则数据丢失
  • 直到被动断开方的应用层代码调用close或shutdown或程序崩溃,协议栈会自动发送fin或RST包

5.RST(连接重置)详解

  • 协议栈发送RST是在本端tcp连接非正常断开时进行的
  • 任意一方发送RST或接收到RST都会进入快速关闭流程,释放相应的资源,然后关闭连接

为什么是四次挥手?

  • 如果是三次挥手,那么可能的情况是:
    • 第二次和第三次挥手合并,也就是和tcp连接的三次握手类似,被动方接收到fin后,协议栈自动发送ack+fin包
    • 三次挥手合并了第二和第三次挥手,最大的不同是:fin由协议栈自动发送,应用层没有权限控制
    • 如果使用三次挥手,那么被动方在发送fin前无法继续发送消息,而且在程序运行过程中进入tcp连接关闭流程,程序员可能并不知道tcp连接关闭的发生,这对代码逻辑有很大的挑战
以上是我个人的理解,下面是gpt-4o的解释:

为什么不能是三次挥手

  1. 可靠性要求
    • TCP协议要求每个FIN和ACK都要独立确认,以确保每一方向另一方清楚地通知了自己的关闭意图。
    • 将ACK和FIN合并在一个包里可能会导致确认过程的不可靠。如果ACK和FIN合并在一个包中,这个包丢失了,将难以确定是否是ACK还是FIN丢失,需要重新发送哪个包。
  2. 流量控制和数据传输的分离
    • 接收FIN包意味着对方已经完成数据发送,但并不意味着接收方也已经完成数据发送。
    • 被动关闭方可能在接收到FIN包后还有数据需要发送,所以它需要有时间处理和发送剩余的数据。
    • 单独的ACK包确保了被动关闭方有时间处理这些数据,而不是立即发送FIN包。
  3. 避免状态混淆
    • 四次挥手的流程清晰地分离了不同的状态:接收FIN、确认FIN、发送FIN、确认关闭。
    • 这种状态分离可以避免在不同阶段的混淆,确保每一步都清楚且明确。

例子解释

如果采用三次挥手,将第二次和第三次挥手合并,情况如下:

  1. 主动关闭方发送FIN。
  2. 被动关闭方接收FIN并发送ACK+FIN。
  3. 主动关闭方接收ACK+FIN,发送ACK,进入TIME_WAIT。

这种情况下:

  • 如果ACK+FIN包丢失,主动关闭方无法区分是ACK还是FIN丢失,需要重新发送哪个包。
  • 被动关闭方在接收到FIN后立即发送ACK+FIN,可能会丢失未发送完的数据。
  • 主动关闭方在接收到ACK+FIN后立即发送ACK并进入TIME_WAIT,可能会导致被动关闭方的数据传输被中断。

结论

四次挥手设计的目的是确保每个关闭步骤都得到确认,保证连接的可靠性和完整性。虽然理论上可以考虑三次挥手,但那样会增加丢包情况下的复杂性和不确定性,违背了TCP协议设计的初衷。四次挥手虽然多了一步,但提供了更高的可靠性和明确的状态分离,有助于实现稳定和可靠的连接关闭过程。
那样会增加丢包情况下的复杂性和不确定性,违背了TCP协议设计的初衷。四次挥手虽然多了一步,但提供了更高的可靠性和明确的状态分离,有助于实现稳定和可靠的连接关闭过程。

推荐学习 https://xxetb.xetslk.com/s/p5Ibb

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 软件测试经理工作日常随记【7】-接口+UI自动化(多端集成测试)
  • 利用Qt实现调用文字大模型的API,文心一言、通义千问、豆包、GPT、Gemini、Claude。
  • Python Beautiful Soup介绍
  • js逻辑或(||)和且()
  • 在Jira中使用AI
  • 【Mind+】掌控板入门教程02 趣味相框
  • CTFHub——XSS——反射型
  • [YashanDB认证]YashanDB个人版安装
  • ECCV 2024 | 深入探索GAN先验,哈工大、清华提出模型反演新方案
  • 校园课程助手【4】-使用Elasticsearch实现课程检索
  • 2024上海初中生古诗文大会暑假备考:单选题真题和独家解析
  • RAG 的优化进阶与引入 Reranker
  • 频率的工程测量01 - Rif算法的构造
  • 双阈值最大最小值筛选
  • 锂离子电池健康状态预测(Part1,Python)
  • @angular/forms 源码解析之双向绑定
  • 【Leetcode】104. 二叉树的最大深度
  • 【前端学习】-粗谈选择器
  • cookie和session
  • Redis的resp协议
  • 从伪并行的 Python 多线程说起
  • 解析带emoji和链接的聊天系统消息
  • 模仿 Go Sort 排序接口实现的自定义排序
  • 人脸识别最新开发经验demo
  • 实现菜单下拉伸展折叠效果demo
  • 小李飞刀:SQL题目刷起来!
  • 学习笔记TF060:图像语音结合,看图说话
  • 用Python写一份独特的元宵节祝福
  • const的用法,特别是用在函数前面与后面的区别
  • ​​​​​​​Installing ROS on the Raspberry Pi
  • (3)医疗图像处理:MRI磁共振成像-快速采集--(杨正汉)
  • (Matalb时序预测)PSO-BP粒子群算法优化BP神经网络的多维时序回归预测
  • (回溯) LeetCode 131. 分割回文串
  • (回溯) LeetCode 46. 全排列
  • (力扣)1314.矩阵区域和
  • (三)Hyperledger Fabric 1.1安装部署-chaincode测试
  • (十八)用JAVA编写MP3解码器——迷你播放器
  • (已解决)vue+element-ui实现个人中心,仿照原神
  • (转)EXC_BREAKPOINT僵尸错误
  • (转)GCC在C语言中内嵌汇编 asm __volatile__
  • (转)大道至简,职场上做人做事做管理
  • .h头文件 .lib动态链接库文件 .dll 动态链接库
  • .NET Core日志内容详解,详解不同日志级别的区别和有关日志记录的实用工具和第三方库详解与示例
  • .Net IE10 _doPostBack 未定义
  • .net 使用$.ajax实现从前台调用后台方法(包含静态方法和非静态方法调用)
  • .net 提取注释生成API文档 帮助文档
  • .Net的DataSet直接与SQL2005交互
  • .net利用SQLBulkCopy进行数据库之间的大批量数据传递
  • @JoinTable会自动删除关联表的数据
  • @德人合科技——天锐绿盾 | 图纸加密软件有哪些功能呢?
  • [ 蓝桥杯Web真题 ]-布局切换
  • [<事务专题>]
  • [3300万人的聊天室] 作为产品的上游公司该如何?
  • [AIGC] HashMap的扩容与缩容:动态调整容量以提高性能
  • [ajaxupload] - 上传文件同时附件参数值