news 2026/5/12 20:02:41

Spring with AI (): 搜索扩展——向量数据库与RAG(上)俺

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Spring with AI (): 搜索扩展——向量数据库与RAG(上)俺

先回顾:三次握手(建立连接)核心流程(实际版)

为了让挥手流程衔接更顺畅,咱们先快速回顾三次握手的实际核心,避免上下文脱节:

第一步(客户端→服务器):客户端发SYN报文发起连接,内核分配临时端口、创建TCB,状态从CLOSED→SYN-SENT;

第二步(服务器→客户端):服务器收SYN后发SYN+ACK报文回应,创建TCB,状态从LISTEN→SYN-RCVD;

第三步(客户端→服务器):客户端收SYN+ACK后发ACK报文(可带数据),状态从SYN-SENT→ESTABLISHED;服务器收ACK后状态→ESTABLISHED,连接正式建立。

连接建立后,双方就可以愉快传输数据了。而当数据传完要关闭连接时,因为TCP是“全双工通信”(双方可同时发数据),不能像建立连接那样简化为三次,必须通过四次交互确认双方都不再发数据,这就是四次挥手的由来。

前置补充:四次挥手的核心前提与关键概念

挥手前先明确两个核心点,避免理解偏差:

1. 全双工通信与关闭逻辑

TCP是全双工协议,客户端和服务器可同时发送数据。因此关闭连接时,要分别确认“客户端→服务器”和“服务器→客户端”两个方向的数据流都已终止,不能一次性关闭双向连接。

2. 新增标记位(FIN)与状态

挥手过程除了用到ACK标记位,还会用到新的标记位FIN(Finish,结束),同时涉及几个新的TCP状态,核心如下:

【FIN=1】:表示发送方已无数据要发,请求关闭自己这边的数据流;

【FIN-WAIT-1】:发送FIN后等待对方ACK的状态;

【CLOSE-WAIT】:收到对方FIN后,确认关闭请求,等待自己这边数据发完再发FIN;

【TIME-WAIT】:客户端最后发完ACK后,等待2MSL(报文最大生存时间),确保对方收到FIN的ACK,避免报文丢失导致重发。

四次挥手全流程:社恐式告别+实际底层交互

咱们依然以“手机退出微信”为例,一边用通俗对话理解逻辑,一边补充操作系统内核、报文交互等实际细节,兼顾易懂性与技术深度。

第一步:主动方发起告别请求(FIN+ACK报文,主动关闭)

场景:你点击微信退出登录,客户端(手机)作为主动关闭方,告知服务器“我这边数据发完了,要关连接了”。

实际行为:微信客户端程序调用close()接口,通知内核关闭连接。客户端内核做两件事:

停止发送新数据,将未发完的数据一次性发完,然后构造FIN+ACK报文(FIN=1表示关闭自身数据流,ACK=1确认之前收到的服务器数据),序号seq=u(u是客户端最后一次发数据的序号+1),确认号ack=v(v是服务器最后一次发数据的序号+1);

发送报文后,释放部分资源,仅保留接收数据的能力(防止服务器还有数据要发)。

拟人对话:客户端(温和):“服务器大佬,我这边数据都发完了,要关我这边的连接了(FIN=1),你之前发的内容我都收到了(ACK=1),你还有要发的吗?”

状态变化:客户端TCP状态从ESTABLISHED→FIN-WAIT-1,开始计时,等待服务器的ACK回应。

第二步:被动方确认告别请求(ACK报文,等待自身数据发完)

场景:微信服务器收到客户端的告别请求,先确认“收到了”,同时继续处理自己这边未发完的数据(比如最后的登录状态同步)。

实际行为:服务器内核收到FIN+ACK报文后,校验序号、确认号无误,然后:

构造ACK报文(ACK=1),序号seq=v,确认号ack=u+1(告知客户端“你的FIN我收到了,你可以不用等我回应了”);

发送ACK后,服务器不会立即关闭连接,而是继续发送自身未完成的数据,此时服务器仅关闭“客户端→服务器”的数据流,自身仍可向客户端发数据。

拟人对话:服务器(沉稳):“收到你的告别请求了(ACK=1),我这边还有点数据没发完,你先等我一下,发完了我再告诉你。”

状态变化:服务器TCP状态从ESTABLISHED→CLOSE-WAIT;客户端收到ACK后,状态从FIN-WAIT-1→FIN-WAIT-2,等待服务器发完数据后发起的FIN报文。

第三步:被动方发起告别请求(FIN+ACK报文,被动关闭)

场景:服务器发完所有数据,告知客户端“我这边也发完了,咱们可以彻底关连接了”。

实际行为:服务器发完剩余数据后,内核构造FIN+ACK报文(FIN=1表示关闭自身数据流,ACK=1确认之前的交互),序号seq=w(w是服务器最后一次发数据的序号+1),确认号ack=u+1(与第二步的ack一致,因为客户端此时已无数据发送),发送给客户端。

拟人对话:服务器(完成收尾):“我这边数据也发完了,要关我这边的连接了(FIN=1),你之前的消息我都收到了(ACK=1),咱们可以告别了。”

状态变化:服务器TCP状态从CLOSE-WAIT→LAST-ACK,开始计时,等待客户端的最终ACK确认。

第四步:主动方最终确认告别(ACK报文,等待超时)

场景:客户端收到服务器的告别请求,确认双方都无数据要发,给出最终回应,同时等待一段时间确保服务器收到回应。

实际行为:客户端内核收到FIN+ACK报文后,校验无误,然后:

构造ACK报文(ACK=1),序号seq=u+1,确认号ack=w+1(告知服务器“你的FIN我收到了,你可以安全关闭了”),发送给服务器;

发送ACK后,客户端不立即关闭连接,而是进入TIME-WAIT状态,等待2MSL(通常是2分钟左右),确保服务器能收到ACK(若服务器没收到,会重发FIN,客户端可再次回应)。等待超时后,释放所有资源和TCB。

拟人对话:客户端(放心):“收到你的告别了(ACK=1),我等一会儿再挂,确保你能收到我的回应,咱们下次见~”

状态变化:客户端TCP状态从FIN-WAIT-2→TIME-WAIT(等待2MSL)→CLOSED;服务器收到ACK后,状态从LAST-ACK→CLOSED,释放所有资源,至此双向连接完全关闭。

可视化流程图:三次握手+四次挥手全链路版

结合连接建立、数据传输、连接关闭的完整链路,用Mermaid图还原内核状态、报文交互全流程:

暂时无法在豆包文档外展示此内容

关键差异与核心疑问解答

1. 为啥挥手要四次,握手却只要三次?

核心原因是“全双工通信”与“连接阶段的特殊性”:

三次握手时,服务器的SYN(同步连接)和ACK(确认客户端)可以合并为一个SYN+ACK报文——因为此时服务器还没有数据要发,同步和确认可以一次性完成;

四次挥手时,服务器收到客户端的FIN后,不能立即发FIN(可能还有数据要发),只能先回一个ACK确认;等数据发完后,再单独发FIN,因此ACK和FIN无法合并,必须分成两步,导致总次数变为四次。

2. TIME-WAIT状态为啥要等2MSL?

主要是两个目的,避免连接残留问题:

确保服务器收到最终ACK:若第四步的ACK丢失,服务器会在超时后重发FIN,2MSL的时间足够客户端收到重发的FIN并再次回应;

避免旧报文干扰新连接:2MSL是报文在网络中的最大生存时间,等待超时后,网络中该连接的所有旧报文都会失效,后续新连接用相同端口也不会被干扰。

3. 常见坑点(实际场景补充)

【CLOSE-WAIT累积】:服务器处于CLOSE-WAIT状态时,若应用程序未及时调用close()发FIN,会导致连接资源泄露,大量CLOSE-WAIT状态会耗尽服务器端口;

【TIME-WAIT过多】:高并发场景下,客户端频繁关闭连接会产生大量TIME-WAIT状态,可通过调整内核参数(如缩短2MSL时间、开启端口复用)优化;

【半关闭连接】:若一方发了FIN但另一方还在发数据,发FIN的一方会拒绝接收数据,导致数据丢失,因此关闭连接前需确保双方都无数据要发。

总结:TCP连接的“始”与“终”,核心都是“可靠”

TCP三次握手与四次挥手,本质都是围绕“可靠传输”设计的流程:三次握手通过双向确认,确保双方通信能力正常,为数据传输铺路;四次挥手通过分步确认,确保双向数据流都已终止,避免数据丢失或残留。笨刻着矢

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/17 20:12:10

开源日程管理利器Calendso:从安装到集成的全流程指南

1. 为什么选择Calendso作为你的日程管理工具? 在快节奏的现代生活中,我们经常需要处理各种会议预约、课程安排等事务。传统的做法是通过邮件或即时通讯工具反复沟通时间,效率低下且容易出错。这就是Calendso这类工具的价值所在——它让时间管…

作者头像 李华
网站建设 2026/4/16 10:43:40

ICMP协议

ICMP协议一、ICMP协议诞生背景与作用1.1 为什么需要ICMP?1.2 ICMP与IP的关系1.3 ICMP的主要功能二、ICMP报文格式与类型2.1 IP 首部2.2 ICMP结构2.3 常见类型与代码2.4 错误报文的特殊格式三、ICMP错误报告详解3.1 目标不可达(类型3)3.2 源点…

作者头像 李华
网站建设 2026/4/17 13:11:34

Linux I/O 演进史:从管道到零拷贝,一篇串起个服务端核心原语骨

前言 在使用 kubectl get $KIND -o yaml 查看 k8s 资源时,输出结果中包含大量由集群自动生成的元数据(如 managedFields、resourceVersion、uid 等)。这些信息在实际复用 yaml 清单时需要手动清理,增加了额外的工作量。 使用 kube…

作者头像 李华
网站建设 2026/4/17 12:56:09

[Refactor]CPP Learn Data Day 咏

一、什么是urllib3? urllib3 是一个用于处理 HTTP 请求和连接池的强大、用户友好的 Python 库。 它可以帮助你: 发送各种 HTTP 请求(GET, POST, PUT, DELETE等)。 管理连接池,提高网络请求效率。 处理重试和重定向。 支…

作者头像 李华
网站建设 2026/4/16 19:26:36

SpringCloud进阶--Sentinel 流量防卫兵怕

一、项目背景与核心价值 1. 解决的核心痛点 Navicat的数据库连接密码并非明文存储,而是通过AES算法加密后写入.ncx格式的XML配置文件中。一旦用户忘记密码,常规方式只能重新配置连接,效率极低。本项目只作为学习研究使用,不做其他…

作者头像 李华
网站建设 2026/4/17 18:14:46

前端八股Vue(6)---v-if和v-for

目录 一、v-for 详解1.1 作用1.2 语法1.3 要点二、v-if 详解2.1 作用2.2 语法2.3 v-if vs v-show三、高频面试坑点:v-for 和 v-if 不能用在同一个标签上3.1 错误示例3.2 原因3.3 正确写法四、v-for 里面的 key 作用4.1 一句话核心答案4.2 详细解释4.3 图解&#xf…

作者头像 李华