TCP 协议详解
目录
一.定义
二.TCP 协议报文格式
三.确认应答(ACK)机制
四.捎带应答
五.连接管理机制
六.滑动窗口
七.快重传
八.拥塞控制
九.延时应答
十.面向字节流
十一.粘包问题
十二.异常情况
十三.TCP 小结
一.定义
传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793 [1]定义。
TCP旨在适应支持多网络应用的分层协议层次结构。 连接到不同但互连的计算机通信网络的主计算机中的成对进程之间依靠TCP提供可靠的通信服务。TCP假设它可以从较低级别的协议获得简单的,可能不可靠的数据报服务。 原则上,TCP应该能够在从硬线连接到分组交换或电路交换网络的各种通信系统之上操作。
我们主要理解以下TCP协议四个特点:
- 传输层协议
- 有连接
- 可靠传输
- 面向字节
通过下面的讲解,你会明白为什么TCP协议具有上述特点。
二.TCP 协议报文格式
报文结构如下:
总体分为俩部分:正文(即上图中数据)+协议报头(除了数据的其他内容)。
下面我们先对部分内容进行讲解:
1. 源/目的端口号: 表示数据是从哪个进程来, 到哪个进程去。
2. 4 位 TCP 报头长度: 表示该 TCP 头部有多少个 32 位 bit(有多少个 4 字节); 所以 TCP 头部最大长度是 15(2的5次方-1) * 4 = 60 字节,即选项内容最多40字节。
3. 6 位标志位(后面详细讲解):
- URG: 紧急指针是否有效
- ACK: 确认号是否有效
- PSH: 提示接收端应用程序立刻从 TCP 缓冲区把数据读走
- RST: 对方要求重新建立连接; 我们把携带 RST 标识的称为复位报文
- SYN: 请求建立连接,我们把携带 SYN 标识的称为同步报文段
- FIN: 通知对方, 本端要关闭了, 我们称携带 FIN 标识的为结束报文
4. 16 位校验和: 发送端填充, CRC 校验. 接收端校验不通过, 则认为数据有问题. 此处的检验和不光包含 TCP 首部, 也包含TCP数据部 。
5. 16 位紧急指针: 标识哪部分数据是紧急数据。当紧急指针置为1,操作系统会优先读取该报文,再读取紧急指针找到紧急数据。
6. 16位窗口大小,表示当前接受数据的剩余空间。
其他协议内容后面讲解。
三.确认应答(ACK)机制
当客户端传输报文时,我们应该如何保证报文被服务端收到呢?让服务端进行回应。打个比方,当我们的辅导员在班群里发送重要通知时,总是会跟上一句收到请回复,当所有人回复收到时,就能保证信息被所有人收到。确认应答机制就是这个原理,简单了解就是收到请回复 。
在这里我们就能明白32位序号和32位确认序号的作用。32位序号,用来标识发送报文的序号,确认序号则是在收到报文为了进行应答,将收到32号序号+1组成确认序号发生给对方进行应答。即32位确认序号=收到的32报文序号+1,用来表示确认序号之前的报文都收到了。
过程如下 :
这里我们可能会有疑问:为什么需要俩个序号?只要有一个32位序号,当收到报文后,回复时用这一个32序号+1发生给对方,也能进行应答。需要俩个32位序号的原因是什么?这就是下面的主题。
四.捎带应答
当客户端给服务端发送报文后,服务端需要对发送的报文进行应答,如果在同时服务端也需要发送报文,那么应答和报文就会一起发送,称为捎带应答。举个例子:你和室友聊天,你问室友,你吃了吗?室友回复:吃了,你作业写了吗?这段对话中,室友的回复包含了应答,同时也传输了信息,就是捎带应答。
这里俩个32位序号就很有必要了,32位确认序号表示应答的,32位序号表示传输信息的。
五.连接管理机制
在正常情况下, TCP 要经过三次握手建立连接, 四次挥手断开连接。我们一一讲解。
我们以客户端主动发起连接,主动断开连接为例子。
三次握手时:
服务端状态转化:
- [CLOSED -> LISTEN] 服务器端调用 listen 后进入 LISTEN 状态, 等待客户端连 接;
- [LISTEN -> SYN_RCVD] 一旦监听到连接请求(同步报文段), 就将该连接放入内核等待队列中, 并向客户端发送 SYN 确认报文.
- [SYN_RCVD -> ESTABLISHED] 服务端一旦收到客户端的确认报文, 就进入 ESTABLISHED 状态, 可以进行读写数据了.
客户端状态转化:
- [CLOSED -> SYN_SENT] 客户端调用 connect, 发送同步报文段;
- [SYN_SENT -> ESTABLISHED] connect 调用成功, 则进入 ESTABLISHED 状 态, 开始读写数据
四次挥手时:
服务端状态转化:
- [ESTABLISHED -> CLOSE_WAIT] 当客户端主动关闭连接(调用 close), 服务器会收到结束报文段, 服务器返回确认报文段并进入 CLOSE_WAIT;
- [CLOSE_WAIT -> LAST_ACK] 进入 CLOSE_WAIT 后说明服务器准备关闭连接(需要处理完之前的数据); 当服务器真正调用 close 关闭连接时, 会向客户端发送 FIN, 此时服务器进入 LAST_ACK 状态, 等待最后一个 ACK 到来(这个 ACK 是客户 端确认收到了 FIN)
[LAST_ACK -> CLOSED] 服务器收到了对 FIN 的 ACK, 彻底关闭连接。
客户端状态转化:
- [ESTABLISHED -> FIN_WAIT_1] 客户端主动调用 close 时, 向服务器发送结 束报文段, 同时进入 FIN_WAIT_1;
- [FIN_WAIT_1 -> FIN_WAIT_2] 客户端收到服务器对结束报文段的确认, 则进 入 FIN_WAIT_2, 开始等待服务器的结束报文段;
- [FIN_WAIT_2 -> TIME_WAIT] 客户端收到服务器发来的结束报文段, 进入 TIME_WAIT, 并发出 LAST_ACK;
- [TIME_WAIT -> CLOSED] 客户端要等待一个 2MSL(Max Segment Life, 报文 最大生存时间)的时间, 才会进入 CLOSED 状态。
这里我们主要理解 TIME_WAIT状态,主动发起断开连接的一端需要经历TIME_WAIT状态。TIME_WAIT状态主要是为了等待一些在网络中或者其他地方已经发送但是还没有到达的数据。如果不进行等待,当重新进行连接时,这些数据到达会引起混乱。
三次握手原因:
- 双方通过两次SYN报文的发送,可以保证全双工通信信道的畅通,同时双方会交换彼此的窗口大小(即接收缓冲区剩余空间)和滑动窗口的头指针位置(后面讲)
- 三次握手中的最后一次ACK应答的可靠性是无法保证的,如果服务端没有收到客户端的ACK应答,则服务端内核将不会浪费资源构建连接相关的结构体,但是客户端在发送ACK应答后(无论ACK应答是否被对方收到),便默认连接建立成功,这种设计的意义在于连接建立失败的资源消耗成本由客户端来承担,从而减小服务器的负担
- 双方协商滑动窗口的头指针起始位置时,会对滑动窗口的头指针起始位置进行随机数映射处理,防止本次通信受到历史通信残留在网络中的报文的干扰
理解四次挥手
- 双方断开连接之前,必须要确认彼此都没有数据要发送给对端,这是双方彼此主动挥手的一个原因
- 主动断开连接的一端,在完成第四次挥手之后,会进入TIME_WAIT状态,等待时间一般为TCP报文在网络中最大存在时长的两倍,这样设计的主要目的是为了等待网络中残存的本次连接的通信报文消散,防止残存报文影响下次连接通信,同时如果第四次挥手的ACK应答丢包,服务器有足够长的时间重新进行第三次挥手,保证连接正常关闭。
六.滑动窗口
刚才我们讨论了确认应答策略, 对每一个发送的数据段, 都要给一个 ACK 确认应答. 收到 ACK 后再发送下一个数据段。这样做有一个比较大的缺点, 就是性能较差. 尤其是数据往返的时间较长的时候。那么我们一次发送多条数据, 就可以大大的提高性能(其实是将多个段的等待时间重叠在一起了)这就是滑动窗口。
滑动窗口可以将数据分为三部分,已发送且收到确认的(左边),滑动窗口中的,未发送的数据(右边)
- 滑动窗口大小指的是无需等待确认应答而可以继续发送数据的最大值. 上图的窗口大小就是 4000 个字节(四个段).在不考虑网络的情况下就是对方报头中的16位窗口大小
- 发送前四个段的时候, 不需要等待任何 ACK, 直接发送;
- 收到第一个 ACK 后, 滑动窗口向后移动, 继续发送第五个段的数据; 依次类推;
- 操作系统内核为了维护这个滑动窗口, 需要开辟 发送缓冲区 来记录当前还有哪 些数据没有应答; 只有确认应答过的数据, 才能从缓冲区删掉;
- 窗口越大, 则网络的吞吐率就越高;
TCP报头中的窗口大小字段用于告知对端己方接收缓冲区剩余空间,同时决定对端单次批量发送的报文数量从而决定对端的滑动窗口大小,即
- 对端滑动窗口的尾指针 = 对端滑动窗口的头指针 + 己方窗口大小(接收缓冲区剩余空间).
这样就实现了TCP 协议中的流量控制.达到接受和发送的平衡.
七.快重传
快重传是基于滑动窗口一种确保TCP协议可靠性的保证,在客户端发送消息时可能发送的消息丢失,也可能是服务端传送的应答丢失,这时除了超时重传,还有一种新的重传机制——快重传。
首先,我们要明白客户端发送的32位序号,就是发送缓存区要发送的字节最大的序号,如下面滑动窗口第一段的消息的32位序号就是2001,回应的报文中32位确认序号就是2002,表示2002之前的字节都收到了,这时滑动窗口会向右滑动到2002。
假设,客户端在发送消息时,第一段1001——2001的消息丢失,其他三段正常发送,那么由于服务器没有收到第一段消息,注意32位确认序号是要表示之前的字节都收到了,服务器没有收到第一段消息,应答的32位确认序号只能是1002,这时客户端就会收到多个确认序号位1002的报文,这时客户端就会明白第一段报文有问题,会启动快重传,重新发送第一段报文。
如果丢失的第二端呢?这时第一段报文的应答是正常的,滑动窗口滑动,第二段变成第一段,情况就和上面一样了。
应答丢失情况类似,如果第一段应答丢失,由于客户端依旧收到了所有消息,第二端应答的32位序号依旧是3002,这时滑动窗口依旧会移动到3002,只是一次性移动。因此滑动窗口也保证了不需要每一个应答都需要收到。如果后面的应答丢失,滑动窗口滑动,情况又一样了,后面的应答就变成了第一段应答。
这里最重要的就是注意32位确认序号是要表示之前的字节都收到了,理解了这个就能全部理解。
八.拥塞控制
在发送数据除了要考虑发送方和接受方的缓存区情况,即做到流量控制,我们还需要考虑网络情况做到拥塞控制。
TCP引入慢启动机制, 先发少量的数据, 探探路, 摸清当前的网络拥堵状态, 再决定按照多大的速度传输数据。
- 此处引入一个概念称为拥塞窗口
- 发送开始的时候, 定义拥塞窗口大小为 1;
- 每次收到一个 ACK 应答, 拥塞窗口加 1;
- 每次发送数据包的时候, 将拥塞窗口和接收端主机反馈的窗口大小做比较, 取较小的值作为实际发送的窗口;即:
网络阻塞情形下滑动窗口的大小
=min(拥塞窗口,ACK窗口大小)
- 当 TCP 开始启动的时候, 慢启动阈值等于窗口最大值;
- 在每次超时重发的时候, 慢启动阈值会变成原来的一半, 同时拥塞窗口置回 1; 少量的丢包, 我们仅仅是触发超时重传; 大量的丢包, 我们就认为网络拥塞; 当 TCP 通信开始后, 网络吞吐量会逐渐上升; 随着网络发生拥堵, 吞吐量会立刻下降;
拥塞控制, 归根结底是 TCP 协议想尽可能快的把数据传输给对方, 但是又要避免给网络 造成太大压力的折中方案。
九.延时应答
如果接收数据的主机立刻返回 ACK 应答, 这时候返回的窗口可能比较小.
- 假设接收端缓冲区为 1M. 一次收到了 500K 的数据; 如果立刻应答, 返回的窗口 就是 500K;
- 但实际上可能处理端处理的速度很快, 10ms 之内就把 500K 数据从缓冲区消费 掉了;
- 在这种情况下, 接收端处理还远没有达到自己的极限, 即使窗口再放大一些, 也 能处理过来;
- 如果接收端稍微等一会再应答, 比如等待 200ms 再应答, 那么这个时候返回的 窗口大小就是 1M;
一定要记得, 窗口越大, 网络吞吐量就越大, 传输效率就越高. 我们的目标是在保证网络 不拥塞的情况下尽量提高传输效率; 那么所有的包都可以延迟应答么? 肯定也不是 。
- 数量限制: 每隔 N 个包就应答一次;
- 时间限制: 超过最大延迟时间就应答一次;
具体的数量和超时时间, 依操作系统不同也有差异; 一般 N取2,超时时间取200ms。
十.面向字节流
创建一个 TCP 的 socket, 同时在内核中创建一个 发送缓冲区和一个接收缓冲区;
- 调用 write 时, 数据会先写入发送缓冲区中;
- 如果发送的字节数太长, 会被拆分成多个 TCP 的数据包发出;
- 如果发送的字节数太短, 就会先在缓冲区里等待, 等到缓冲区长度差不多了, 或 者其他合适的时机发送出去;
- 接收数据的时候, 数据也是从网卡驱动程序到达内核的接收缓冲区;
- 然后应用程序可以调用 read 从接收缓冲区拿数据;
- 另一方面, TCP 的一个连接, 既有发送缓冲区, 也有接收缓冲区, 那么对于这一 个连接, 既可以读数据, 也可以写数据. 这个概念叫做全双工
由于缓冲区的存在, TCP 程序的读和写不需要一一匹配, 例如:
- 写 100 个字节数据时, 可以调用一次 write 写 100 个字节, 也可以调用 100 次 write, 每次写一个字节;
- 读 100 个字节数据时, 也完全不需要考虑写的时候是怎么写的, 既可以一次 read 100 个字节, 也可以一次 read 一个字节, 重复 100 次;
十一.粘包问题
首先要明确, 粘包问题中的 "包" , 是指的应用层的数据包.
- • 在 TCP 的协议头中, 没有如同 UDP 一样的 "报文长度" 这样的字段, 但是有一 个序号这样的字段. • 站在传输层的角度, TCP 是一个一个报文过来的. 按照序号排好序放在缓冲区中.
- • 站在应用层的角度, 看到的只是一串连续的字节数据.
- • 那么应用程序看到了这么一连串的字节数据, 就不知道从哪个部分开始到哪个部分, 是一个完整的应用层数据包.
那么如何避免粘包问题呢? 归根结底就是一句话, 明确两个包之间的边界.
- 对于定长的包, 保证每次都按固定大小读取即可; 例如上面的 Request 结构, 是固定大小的, 那么就从缓冲区从头开始按 sizeof(Request)依次读取即可;
- 对于变长的包, 可以在包头的位置, 约定一个包总长度的字段, 从而就知道了包的结束位置;
- 对于变长的包, 还可以在包和包之间使用明确的分隔符(应用层协议, 是程序猿 自己来定的, 只要保证分隔符不和正文冲突即可)
主要我们是通过应用层协议来避免TCP中的粘包问题。
十二.异常情况
- 进程终止: 进程终止会释放文件描述符, 仍然可以发送 FIN. 和正常关闭没有什么区别.
- 机器重启: 和进程终止的情况相同. 机器掉电/网线断开: 接收端认为连接还在, 一旦接收端有写入操作, 接收端发现连接已 经不在了, 就会进行 reset. 即使没有写入操作, TCP 自己也内置了一个保活定时器, 会 定期询问对方是否还在. 如果对方不在, 也会把连接释放. 另外, 应用层的某些协议, 也有一些这样的检测机制. 例如 HTTP 长连接中, 也会定期检测对方的状态. 例如 QQ, 在 QQ 断线之后, 也会定期尝试重新连接.
十三.TCP 小结
为什么 TCP 这么复杂? 因为要保证可靠性, 同时又尽可能的提高性能。
可靠性: • 校验和 • 序列号(按序到达) • 确认应答 • 超时重发 • 连接管理 • 流量控制 • 拥塞控制
提高性能: • 滑动窗口 • 快速重传 • 延迟应答 • 捎带应答
其他: • 定时器(超时重传定时器, 保活定时器, TIME_WAIT 定时器等)
基于 TCP 应用层协议 • HTTP • HTTPS • SSH • Telnet • FTP • SMTP 当然, 也包括你自己写TCP 程序时自定义的应用层协议。
相关文章:

TCP 协议详解
目录 一.定义 二.TCP 协议报文格式 三.确认应答(ACK)机制 四.捎带应答 五.连接管理机制 六.滑动窗口 七.快重传 八.拥塞控制 九.延时应答 十.面向字节流 十一.粘包问题 十二.异常情况 十三.TCP 小结 一.定义 传输控制协议(TCP,Transmissio…...

【转载】golang内存分配
Go 的分配采用了类似 tcmalloc 的结构.特点: 使用一小块一小块的连续内存页, 进行分配某个范围大小的内存需求. 比如某个连续 8KB 专门用于分配 17-24 字节,以此减少内存碎片. 线程拥有一定的 cache, 可用于无锁分配. 同时 Go 对于 GC 后回收的内存页, 并不是马上归还给操作系…...

TPM管理培训:学以致用,才是硬道理
全面生产维护(TotalProductiveMaintenance,TPM)作为一种先进的管理体系,正被越来越多的企业所采用,以期通过全员参与、全系统改善的方式,实现设备综合效率的最大化。然而,理论学习与实践应用之间往往存在鸿…...

2024年六月英语四级真题及解析PDF共9页
2024年六月英语四级真题及解析PDF共9页,真题就是最好的复习资料,希望对大家有所帮助。...

自闭症儿童语言干预
自闭症儿童的语言发展往往面临独特挑战,这不仅影响了他们的日常交流能力,也制约了其社交与认知的全面发展。因此,实施科学有效的语言干预对于促进自闭症儿童的语言能力至关重要。 语言干预应基于个性化原则,充分考虑每个孩子的兴…...
webpack基本使用(基础配置)
文章目录 概要理解 一、使用示例1.引入库2.创建config/webpack.dev.js 测试环境3.创建config/webpack.prod.js 正式环境3.创建eslintrc.js4.创建babel.config.js5.package.json5.main.js 总结 概要理解 vue或者react 通常用webpack作为打包工具,打包成浏览器识别的…...

在js渲染的dom中的事件中传递对象
在某些情况下,可能需要将整个对象或部分对象嵌入到 HTML 元素的属性中,可以将对象数据序列化为 JSON 字符串,存储在 data-* 自定义属性中。这样可以在事件中取出并解析对象数据: <!DOCTYPE html> <html lang"en&qu…...
服务器加速器如何应对大规模并行计算需求
服务器加速器,如GPU(图形处理单元)、FPGA(现场可编程门阵列)和TPU(张量处理单元),在大规模并行计算需求中发挥着重要作用。它们通过提供高效的并行处理能力,大幅提升了计算性能,满足了许多领域对大规模并行计算的需求。下面详细介…...
C++/Qt 多媒体(续四)
一、前言 前边讲述到了Qt的两项独特的模块编程支持的另一项内容——多媒体编程,上篇文章具体讲述的包括采集和播放原始音频相关类的概述,而本章开始主要概述多媒体编程实现的功能中的最后两项:播放视频文件和通过摄像头拍照和录像。 对于上篇内容的示例全部代码,可…...

怎样把flv转换成mp4格式?8种可以推荐的视频转换方法
怎样把flv转换成mp4格式?MP4格式因其广泛的兼容性,几乎可以在所有设备和媒体播放器上顺畅播放,这极大地方便了用户的观看体验。与flv文件相比,MP4通常能更有效地压缩视频文件,既能保持较高的画质,又能显著减…...
【2024数学建模国赛赛题解析已出】原创免费分享
2024数模国赛赛题已正式发布 数模加油站初步分析评估了此次竞赛题目: A题:偏数学仿真建模,难度偏难,适合数学专业背景的同学 B题:评价决策类,自由度大,容易水,适合基础不太好的同…...

Windows安装使用Docker
配置Dorker环境 启用或关闭windows功能 安装wsl 以管理员身份打开windows PowerShell,安装相关配置 下载docker应用程序 Releases tech-shrimp/docker_installer (github.com) 安装Docker 指定安装位置 默认双击程序就开始安装了,要安装在指定位置…...

【wsl2】从C盘迁移到G盘
参考大神 C盘的ubuntu22.04 非常大,高达30g 迁移后就只有几百M了: 右键有一个move没有敢尝试 迁移过程 Windows PowerShell Copyright (C) Microsoft Corporation. All rights reserved.Install the latest PowerShell for new features and improveme…...

低代码技术新趋势——逆向工程
低代码的下一个趋势,应该是“逆向工程”,用户可以通过 可视化界面,逆向输出全栈工程代码。而标准的工程代码同样可以编译为支持可视化分析、编辑、调整的“无代码”程序。前一个是解释性语言向编译性语言的逆向工程。后者则是一个理论实践应用…...

HTTP 二、进阶
四、安全 1、TLS是什么 (1)为什么要有HTTPS 简单的回答是“因为 HTTP 不安全”。由于 HTTP 天生“明文”的特点,整个传输过程完全透明,任何人都能够在链路中截获、修改或者伪造请求 / 响应报文,数据不具有可…...

【Hot100】LeetCode—35. 搜索插入位置
目录 1- 思路二分 2- 实现⭐35. 搜索插入位置——题解思路 3- ACM 实现 题目连接:35. 搜索插入位置 1- 思路 二分 二分左区间的三种情况。由于目标值不一定在数组中,因此二分的过程中有三种情况判断 2- 实现 ⭐35. 搜索插入位置——题解思路 class So…...

001集——CAD—C#二次开发入门——开发环境基本设置
CAD C#二次开发首先需要搭建一个舒服的开发环境,软件安装后,需要修改相关设置。本文为保姆级入门搭建开发环境教程,默认已成功安装vs和cad 。 第一步:创建类库 第二步:进行相关设置,如图: 下一…...

Java类和对象——快速自动生成带参数的结构
1.鼠标点击右键或者(使用快捷按键:AltInsert) 2.选着generate 3.选择想要执行的指令 其中Constructor---构造方法(声明了private属性然后直接使用即可),生成带参数的结构 1:不带参数的结构&…...
Python操作数据库的ORM框架SQLAlchemy快速入门教程
连接内存版SQLIte from sqlalchemy import create_engineengine create_engine(sqlite:///:memory:) print(engine)连接文件版SQLite from sqlalchemy import create_engineengine create_engine(sqlite:///sqlite3.db) print(engine)连接MySQL数据库 from sqlalchemy imp…...

提交MR这个词儿您知道是什么意思吗?
作为测试的同学,是不是经常会听研发同学说提交MR呢?那么究竟什么是提交MR呢?在这篇文章中会告诉大家! 在Git中,提交MR(Merge Request,合并请求)是在进行协作开发的一种常见方式&…...

CentOS下的分布式内存计算Spark环境部署
一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架,相比 MapReduce 具有以下核心优势: 内存计算:数据可常驻内存,迭代计算性能提升 10-100 倍(文档段落:3-79…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...

[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...

C++使用 new 来创建动态数组
问题: 不能使用变量定义数组大小 原因: 这是因为数组在内存中是连续存储的,编译器需要在编译阶段就确定数组的大小,以便正确地分配内存空间。如果允许使用变量来定义数组的大小,那么编译器就无法在编译时确定数组的大…...
人工智能--安全大模型训练计划:基于Fine-tuning + LLM Agent
安全大模型训练计划:基于Fine-tuning LLM Agent 1. 构建高质量安全数据集 目标:为安全大模型创建高质量、去偏、符合伦理的训练数据集,涵盖安全相关任务(如有害内容检测、隐私保护、道德推理等)。 1.1 数据收集 描…...
如何配置一个sql server使得其它用户可以通过excel odbc获取数据
要让其他用户通过 Excel 使用 ODBC 连接到 SQL Server 获取数据,你需要完成以下配置步骤: ✅ 一、在 SQL Server 端配置(服务器设置) 1. 启用 TCP/IP 协议 打开 “SQL Server 配置管理器”。导航到:SQL Server 网络配…...
LangChain 中的文档加载器(Loader)与文本切分器(Splitter)详解《二》
🧠 LangChain 中 TextSplitter 的使用详解:从基础到进阶(附代码) 一、前言 在处理大规模文本数据时,特别是在构建知识库或进行大模型训练与推理时,文本切分(Text Splitting) 是一个…...