【网络编程】深入理解TCP协议二(连接管理机制、WAIT_TIME、滑动窗口、流量控制、拥塞控制)

TCP协议
- 1.连接管理机制
- 2.再谈WAIT_TIME状态
- 2.1理解WAIT_TIME状态
- 2.2解决TIME_WAIT状态引起的bind失败的方法
- 2.3监听套接字listen第二个参数介绍
- 3.滑动窗口
- 3.1介绍
- 3.2丢包情况分析
- 4.流量控制
- 5.拥塞控制
- 5.1介绍
- 5.2慢启动
- 6.捎带应答、延时应答
1.连接管理机制
正常情况下,TCP需要经过三次握手建立连接+四次挥手断开链接,下面看一个图:

- 服务器的状态变化:
- [CLOSED -> LISTEN] 服务器端调用listen后进入LISTEN状态, 等待客户端连接;
- [LISTEN -> SYN_RCVD] 一旦监听到连接请求(同步报文段), 就将该连接放入内核等待队列中, 并向客户端发送SYN确认报文.
- [SYN_RCVD -> ESTABLISHED] 服务端一旦收到客户端的确认报文, 就进入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, 彻底关闭连接.
- 客户端状态变化
- [CLOSED -> SYN_SENT] 客户端调用connect, 发送同步报文段;
- [SYN_SENT -> ESTABLISHED] connect调用成功, 则进入ESTABLISHED状态, 开始读写数据;
- [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状态.
2.再谈WAIT_TIME状态
2.1理解WAIT_TIME状态
现在做一个测试,首先启动server,然后启动client,然后用Ctrl-C使server终止,这时马上再运行server, 结果是:

这是因为,虽然server的应用程序终止了,但TCP协议层的连接并没有完全断开,因此不能再次监 听同样的server端口.
我们用netstat命令查看一下:

TCP协议规定,主动关闭连接的一方要处于TIME_ WAIT状态,等待两个MSL(maximum segment lifetime)的时间后才能回到CLOSED状态.
我们使用Ctrl-C终止了server, 所以server是主动关闭连接的一方, 在TIME_WAIT期间仍然不能再次监听同样的server端口;
MSL在RFC1122中规定为两分钟,但是各操作系统的实现不同, 在Centos7上默认配置的值是60s;
可以通过 cat /proc/sys/net/ipv4/tcp_fin_timeout 查看msl的值;
- 为什么TIME_WAIT的时间是2MSL?
MSL是TCP报文的最大生存时间, 因此TIME_WAIT持续存在2MSL的话
就能保证在两个传输方向上的尚未被接收或迟到的报文段都已经消失(否则服务器立刻重启, 可能会收到来自上一个进程的迟到的数据, 但是这种数据很可能是错误的);
同时也是在理论上保证最后一个报文可靠到达(假设最后一个ACK丢失, 那么服务器会再重发一个FIN. 这时虽然客户端的进程不在了, 但是TCP连接还在, 仍然可以重发LAST_ACK);
2.2解决TIME_WAIT状态引起的bind失败的方法
- 在server的TCP连接没有完全断开之前不允许重新监听, 某些情况下可能是不合理的
服务器需要处理非常大量的客户端的连接(每个连接的生存时间可能很短, 但是每秒都有很大数量的客户端来请求).
这个时候如果由服务器端主动关闭连接(比如某些客户端不活跃, 就需要被服务器端主动清理掉), 就会产
生大量TIME_WAIT连接.由于我们的请求量很大, 就可能导致TIME_WAIT的连接数很多, 每个连接都会占用一个通信五元组(源ip,源端口, 目的ip, 目的端口, 协议). 其中服务器的ip和端口和协议是固定的. 如果新来的客户端连接的ip和端口号和TIME_WAIT占用的链接重复了, 就会出现问题.
- setsockopt函数介绍
setsockopt 是一个用于设置套接字选项的函数,通常用于配置套接字的各种属性。它可以被用于不同类型的套接字,如 TCP 套接字和 UDP 套接字,以及其他类型的网络套接字。setsockopt 允许你在编程中控制套接字的行为和参数。
下面是 setsockopt 函数的常用参数:
套接字描述符(Socket Descriptor):指定要设置选项的套接字描述符。
- 层级(Level):指定选项的所属协议族或协议层级,如 SOL_SOCKET 表示通用套接字选项,IPPROTO_TCP 表示 TCP 协议选项,IPPROTO_IP 表示 IP 协议选项等。
- 选项名称(Option Name):指定要设置的选项名称,如 SO_REUSEADDR 表示重用本地地址选项,TCP_NODELAY 表示禁用 Nagle 算法选项等。
- 选项值(Option Value):设置选项的新值,这个值的数据类型和选项名称有关,通常是一个指向某种数据类型的指针,例如 int、struct timeval 等。
- 选项值的长度(Option Length):指定选项值的长度。
通过 setsockopt,你可以配置诸如套接字缓冲区大小、重用地址、禁用 Nagle 算法、设置超时等多种选项,以满足你的网络通信需求。这个函数在网络编程中经常用于优化套接字的性能和行为,确保数据传输的可靠性和效率。- 需要注意的是,setsockopt 函数的错误处理很重要,因为配置错误的套接字选项可能导致不稳定的网络行为或错误。因此,在使用该函数时,建议检查返回值以确保选项设置成功。
- 实际案例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netinet/tcp.h>int main() {// 创建 TCP 套接字int sockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd < 0) {perror("socket");exit(EXIT_FAILURE);}// 设置 TCP 连接超时时间为 5 秒struct timeval timeout;timeout.tv_sec = 5; // 5 秒timeout.tv_usec = 0;if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0) {perror("setsockopt");close(sockfd);exit(EXIT_FAILURE);}// 尝试连接到远程服务器struct sockaddr_in server_addr;memset(&server_addr, 0, sizeof(server_addr));server_addr.sin_family = AF_INET;server_addr.sin_port = htons(80); // HTTP 默认端口inet_pton(AF_INET, "www.example.com", &(server_addr.sin_addr));if (connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {perror("connect");close(sockfd);exit(EXIT_FAILURE);}printf("Connected to www.example.com\n");// 在这里可以进行后续的数据交换或操作// 关闭套接字close(sockfd);return 0;
}
在上面的示例中,我们创建了一个 TCP 套接字,并使用 setsockopt 设置了接收超时时间为 5 秒。然后,我们尝试连接到 www.example.com 的 HTTP 服务。如果连接在 5 秒内成功建立,将打印 “Connected to www.example.com”。否则,连接超时会导致 connect 失败,错误处理部分将处理超时情况。
2.3监听套接字listen第二个参数介绍
if(listen(listenSock,2)<0)
{
exit(3);
}
在这里的2表示什么?当服务器在处理其他请求时来不及处理新的链接请求,监听套接字所维护的最大链接数为:2+1,相当于排队
listen底层有个backlog来维护:
backlog 是 TCP 套接字选项之一,它用于指定操作系统中已完成连接队列的最大长度。在网络编程中,当服务器接受到客户端的连接请求时,操作系统会将这些请求存储在一个已完成连接队列中,等待服务器进程调用 accept 来接受这些连接。backlog 参数控制了这个队列的最大长度。
- 下面是关于 backlog 的一些重要信息:
- 作用:backlog 的主要作用是限制已完成连接队列的长度,以防止服务器处理不过来的连接请求。它允许服务器在高负载情况下接受连接请求,并将未处理的连接请求排队等待处理。
- 默认值:backlog 的默认值在不同的操作系统上可能有所不同。通常,操作系统会提供一个合理的默认值,但这个值可能不足以处理高负载情况。
- 合适的值:合适的 backlog 值取决于服务器的负载和性能要求。如果服务器期望高并发连接,应该将 backlog 设置为较大的值,以便排队更多的连接请求。但是,设置太大的值可能会占用过多的系统资源,因此需要权衡。
- 超出 backlog 的连接请求:如果有更多的连接请求到达服务器,超过了 backlog 设置的大小,这些连接请求可能会被服务器拒绝或丢弃,具体行为取决于操作系统和服务器的配置。
- 动态调整:一些服务器应用程序支持在运行时动态调整 backlog 值,以根据服务器的当前负载和性能要求进行优化。这可以通过重新设置套接字选项来实现。
- 总之,backlog 是一个重要的套接字选项,用于控制服务器的连接排队行为。合适的 backlog 值应该根据服务器的性能需求和负载情况来配置,以确保服务器能够有效地处理连接请求。
这其实也是一种池化技术,进行排队等待处理,
- 排队的意义在于:可以让服务器在有闲置的情况下,拿到链接处理相关任务,减少资源的闲置,提高利用率。
- 为什么不能设置过长:1.太长的排队影响处理效率,新的任务需要等待很长的时间才能处理,影响客户体验;2.队列也是会占用系统资源的,设置过长占用过多的系统资源,反而可能导致服务器的效率降低!
3.滑动窗口
3.1介绍
- 定义:滑动窗口是一个用于管理数据传输的窗口或缓冲区,通常由接收方控制。这个窗口可以看作是接收方的一个缓冲区,用于存储将要接收的数据包。发送方根据窗口的大小和接收方的状态来确定可以发送多少数据包。
- 工作原理:滑动窗口的大小以数据包数量为单位。发送方和接收方都维护一个窗口大小的计数器。发送方将数据包发送到接收方,并等待接收方确认。一旦接收方确认收到数据包,发送方就可以向前滑动窗口,发送下一个数据包。接收方使用窗口大小来控制允许接收的数据包数量,一旦接收方处理了一个数据包,它可以向前滑动窗口以接收下一个数据包。
- 流量控制:滑动窗口用于流量控制,以确保发送方不会发送太多数据导致接收方无法处理。接收方可以通过减小窗口大小来通知发送方减慢数据传输速度。这种机制可防止数据包的堆积和丢失。
- 拥塞控制:滑动窗口也用于拥塞控制,帮助避免网络拥塞。当网络出现拥塞时,接收方可以减小窗口大小,通知发送方降低传输速度,从而减轻网络负载。
- 实时调整:滑动窗口的大小通常可以动态调整,以适应网络条件的变化。这种动态调整可以根据网络延迟、丢包率等指标来执行,以确保最佳的性能。
- 应用:滑动窗口广泛应用于TCP协议中,用于实现可靠的数据传输和流量控制。它还用于一些应用层协议,如HTTP,以管理并发连接和数据传输。
- 没有滑动窗口情况下通信:

既然这样一发一收的方式性能较低, 那么我们一次发送多条数据, 就可以大大的提高性能(其实是将多个段的等待时间重叠在一起了).

窗口大小指的是无需等待确认应答而可以继续发送数据的最大值. 上图的窗口大小就是4000个字节(四个段).
发送前四个段的时候, 不需要等待任何ACK, 直接发送;
收到第一个ACK后, 滑动窗口向后移动, 继续发送第五个段的数据; 依次类推;
操作系统内核为了维护这个滑动窗口, 需要开辟 ** 发送缓冲区 ** (没有收到确认时需要重传) 来记录当前还有哪些数据没有应答;
只有确认应答过的数据, 才能从缓冲区删掉;
窗口越大, 则网络的吞吐率就越高;
3.2丢包情况分析
-
情况一: 数据包已经抵达, ACK被丢了

这种情况下, 部分ACK丢了并不要紧, 因为可以通过后续的ACK进行确认,也就是说:主机A给主机B发送1~6000号数据包,主机B已经收到了,但是其中的确认请求1001(确认前1000号)和2001、3001、4001、主机A都没有收到,但是6001收到了,这就说明前6000号数据包已经成功接收!!! 如果说出现这样一种情况:1000–2000号数据包丢了,其他的数据包成功接收,那么主机B并不会确认6001号,而是确认1001,表示后面的丢失,这时候就要进行重传! -
情况二: 数据包就直接丢了.

当某一段报文段丢失之后, 发送端会一直收到 1001 这样的ACK, 就像是在提醒发送端 "我想要的是 1001"一样;
如果发送端主机连续三次收到了同样一个 “1001” 这样的应答, 就会将对应的数据 1001 - 2000 重新发送;
这个时候接收端收到了 1001 之后, 再次返回的ACK就是7001了(因为2001 - 7000)接收端其实之前就已经收到了, 被放到了接收端操作系统内核的接收缓冲区中;
- 这种机制被称为 “高速重发控制”(也叫 “快重传”).
4.流量控制
接收端处理数据的速度是有限的. 如果发送端发的太快, 导致接收端的缓冲区被打满, 这个时候如果发送端继续发送,就会造成丢包, 继而引起丢包重传等等一系列连锁反应.
因此TCP支持根据接收端的处理能力, 来决定发送端的发送速度. 这个机制就叫做流量控制(Flow Control);
接收端将自己可以接收的缓冲区大小放入 TCP 首部中的 “窗口大小” 字段, 通过ACK端通知发送端;
窗口大小字段越大, 说明网络的吞吐量越高;
接收端一旦发现自己的缓冲区快满了, 就会将窗口大小设置成一个更小的值通知给发送端;
发送端接受到这个窗口之后, 就会减慢自己的发送速度;
如果接收端缓冲区满了, 就会将窗口置为0; 这时发送方不再发送数据, 但是需要定期发送一个窗口探测数据段, 使接收端把窗口大小告诉发送端.

接收端如何把窗口大小告诉发送端呢? 回忆我们的TCP首部中, 有一个16位窗口字段, 就是存放了窗口大小信息;
那么问题来了, 16位数字最大表示65535, 那么TCP窗口最大就是65535字节么?
实际上, TCP首部40字节选项中还包含了一个窗口扩大因子M, 实际窗口大小是 窗口字段的值左移 M 位;
5.拥塞控制
5.1介绍
拥塞控制(Congestion Control)是计算机网络中的一种重要机制,用于管理网络拥塞的发生和传播,以保持网络的稳定性和性能。拥塞通常发生在网络上的某个点或链路上,当网络负载超过其容量时,数据包开始堆积、丢失或延迟增加,从而降低了网络的效率和可用性。
拥塞控制的主要目标是防止和减轻网络拥塞,确保网络吞吐量最大化,同时避免过多的数据包丢失。以下是拥塞控制的一些关键概念和技术:
- 拥塞窗口:拥塞控制使用拥塞窗口(Congestion Window,通常缩写为cwnd)来限制发送方可以发送到网络的数据包数量。拥塞窗口的大小决定了发送方可以在网络上发送的数据包的数量。发送方会根据网络的拥塞程度来动态调整拥塞窗口的大小。
- 拥塞信号:网络中的路由器和交换机会在发生拥塞时向发送方发送拥塞信号。这些信号可以是丢弃数据包、降低数据包优先级或发送拥塞通知等方式。发送方根据这些信号来减少发送速率。
- 慢启动:慢启动是一种拥塞控制算法,用于在连接开始时逐渐增加发送速率,以避免立即引发网络拥塞。发送方开始时只发送少量数据包,然后根据网络的反馈逐渐增加发送速率。
- 拥塞避免:一旦拥塞窗口达到某个阈值,发送方进入拥塞避免阶段。在这个阶段,发送方以更加保守的速率增加拥塞窗口,以避免引发拥塞。
- 快重传和快恢复:快重传和快恢复是一种机制,用于更快地检测和响应数据包丢失。当接收方收到无序的数据包时,它可以立即向发送方发送重复确认,以触发发送方进行快速重传和快速恢复。
- 主动队列管理:路由器和交换机可以使用主动队列管理算法来减轻拥塞。这些算法可以根据网络负载动态管理数据包的排队,以防止拥塞的发生。
- 流量控制和窗口调整:拥塞控制和流量控制有时会被混淆,但它们有不同的目标。流量控制是为了防止接收方被发送方的数据淹没,而拥塞控制是为了防止网络拥塞。窗口大小的调整是拥塞控制的核心部分。
- 拥塞控制在现代计算机网络中至关重要,它确保了网络的稳定性和性能。通过动态调整数据包的发送速率和响应网络拥塞,拥塞控制确保了数据的可靠传输,并提供了更好的用户体验。不同的拥塞控制算法和机制可以根据网络类型和需求进行选择和配置。
5.2慢启动

此处引入一个概念程为拥塞窗口
发送开始的时候, 定义拥塞窗口大小为1;
每次收到一个ACK应答, 拥塞窗口加1;
每次发送数据包的时候, 将拥塞窗口和接收端主机反馈的窗口大小做比较, 取较小的值作为实际发送的窗口
- 像上面这样的拥塞窗口增长速度, 是指数级别的. “慢启动” 只是指初使时慢, 但是增长速度非常快.
为了不增长的那么快, 因此不能使拥塞窗口单纯的加倍.
此处引入一个叫做慢启动的阈值
当拥塞窗口超过这个阈值的时候, 不再按照指数方式增长, 而是按照线性方式增长

当TCP开始启动的时候, 慢启动阈值等于窗口最大值;
在每次超时重发的时候, 慢启动阈值会变成原来的一半, 同时拥塞窗口置回1;
少量的丢包, 我们仅仅是触发超时重传; 大量的丢包, 我们就认为网络拥塞;
当TCP通信开始后, 网络吞吐量会逐渐上升; 随着网络发生拥堵, 吞吐量会立刻下降;
拥塞控制, 归根结底是TCP协议想尽可能快的把数据传输给对方, 但是又要避免给网络造成太大压力的折中方案.
6.捎带应答、延时应答
相关博客: 点击跳转
相关文章:
【网络编程】深入理解TCP协议二(连接管理机制、WAIT_TIME、滑动窗口、流量控制、拥塞控制)
TCP协议 1.连接管理机制2.再谈WAIT_TIME状态2.1理解WAIT_TIME状态2.2解决TIME_WAIT状态引起的bind失败的方法2.3监听套接字listen第二个参数介绍 3.滑动窗口3.1介绍3.2丢包情况分析 4.流量控制5.拥塞控制5.1介绍5.2慢启动 6.捎带应答、延时应答 1.连接管理机制 正常情况下&…...
社区团购商城小程序v18.1开源独立版+前端
新增后台清理缓存功能 修复定位权限 修复无法删除手机端管理员 11月新登录接口修复! 修复商家付款到零钱, 修复会员登陆不显示头像, 修复无法修改会员开添加绑定...
MATLAB入门-字符串操作
MATLAB入门-字符串操作 注:本篇文章是学习笔记,课程链接是:link MATLAB中的字符串特性: 无论是字符还是字符串,都要使用单引号来‘’表示;在MATLAB中,字符都是在矩阵中存储的,无论…...
Kong Learning
一、Kong Kong是由Mashape公司开源的可扩展的Api GateWay项目。它运行在调用Api之前,以插件的扩展方式为Api提供了管理。比如,鉴权、限流、监控、健康检查等,Kong是基于lua语言、nginx以及openResty开发的,所有拥有动态路由、负载…...
Python怎样写桌面程序
要编写Python桌面应用程序,可以使用以下几种方法: 1.使用Tkinter模块:Tkinter是Python自带的GUI工具包之一,可以使用它来创建基本的GUI界面。例如,可以创建一个简单的窗口,添加按钮、文本框等控件…...
蓝桥杯2023年第十四届省赛真题-平方差--题解
蓝桥杯2023年第十四届省赛真题-平方差 时间限制: 3s 内存限制: 320MB 提交: 2379 解决: 469 题目描述 给定 L, R,问 L ≤ x ≤ R 中有多少个数 x 满足存在整数 y,z 使得 x y2 − z2。 输入格式 输入一行包含两个整数 L, R,用一个空格分隔。 输出格…...
iText实战--根据绝对位置添加内容
3.1 direct content 概念简介 pdf内容的4个层级 层级1:在text和graphics底下,PdfWriter.getDirectContentUnder() 层级2:graphics层,Chunk, Images背景,PdfPCell的边界等 层级3:text层,Chun…...
使用navicat for mongodb连接mongodb
使用navicat for mongodb连接mongodb 安装navicat for mongodb连接mongodb 安装navicat for mongodb 上文mongodb7.0安装全过程详解我们说过,在安装的时候并没有勾选install mongodb compass 我们使用navicat去进行可视化的数据库管理 navicat for mongodb下载地址…...
Qt ffmpeg音视频转换工具
Qt ffmpeg音视频转换工具,QProcess方式调用ffmpeg,对音视频文件进行格式转换,支持常见的音视频格式,主要在于QProcess的输出处理以及转换的文件名和后缀的处理,可以进一步加上音视频剪切合并和音视频文件属性查询修改的…...
机器学习笔记 - 视频分析和人类活动识别技术路线简述
一、理解人类活动识别 首先了解什么是人类活动识别,简而言之,是对某人正在执行的活动/动作进行分类或预测的任务称为活动识别。 我们可能会有一个问题:这与普通的分类任务有什么不同?这里的问题是,在人类活动识别中,您实际上需要一系列数据点来预测正确执行的动作。 看看…...
Redis从入门到精通(三:常用指令)
前边我们介绍了redis存储的四种基本数据类型,并纵向介绍了这四种数据类型的各种指令操作,现在我们这个章节从横向来总结一下关于key的常用指令和数据库常用指令 key常用指令 删除指定key del key 获取key是否存在 exists key 获取key的类型 type …...
代码随想录day39 || 动态规划 || 不同路径
62.不同路径 ● 力扣题目链接 ● 一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。 ● 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。 ● 问总共有…...
电商平台API接口采集电商平台淘宝天猫京东拼多多数据获取产品详情信息,销量,价格,sku案例
淘宝SKU详情接口是指,获取指定商品的SKU(Stock Keeping Unit,即库存量单位)的详细信息。SKU是指提供不同的商品参数组合的一个机制,通过不同的SKU来标识商品的不同组合形式,如颜色、尺寸等。SKU详情接口可以…...
The ‘<‘ operator is reserved for future use. 错误解决
The < operator is reserved for future use. 错误解决 在 PowerShell 终端执行 python learnstock.py < ldata.txt 发生错误, The < operator is reserved for future use.解决方法, cmd /c python learnstock.py < ldata.txt完结&#x…...
vulnhub靶机Thoth-Tech
下载地址:https://download.vulnhub.com/thothtech/Thoth-Tech.ova 主机发现 arp-scan -l 目标:192.168.21.148 端口扫描 nmap --min-rate 10000 -p- 192.168.21.148 服务扫描 nmap -sV -sT -O -p21,22,80 192.168.21.148 漏洞扫描 nmap --scriptvu…...
不可思议,无密码登录所有网站!
hello,我是小索奇 居然可以免密码登录你的网站?听起来是不是很恐怖 确实如此,Cookie可以用于保持用户在网站上的登录状态,从而实现 免密码登录,学会了不要做坏事哈 这里仅做免密码登录的实操,就不介绍Cooki…...
深度学习编译器关键组件
1 高层中间代码 为了克服传统编译器中采用的IR限制DL模型中复杂计算的表达的局限性,现有的DL编译器利用高层IR(称为图IR)进行高效的代码优化设计。 1.1 图表示 基于DAG的IR:基于DAG的IR是编译器构建计算图的最传统方法之一&…...
【C++】string类模拟实现下篇(附完整源码)
目录 1. resize2. 流插入<<和流提取>>重载2.1 流插入<<重载2.2 流提取 << 3. 常见关系运算符重载4. 赋值重载4.1浅拷贝的默认赋值重载4.2 深拷贝赋值重载实现4.3 赋值重载现代写法 5. 写时拷贝(了解)6.源码6.1 string.h6.2 test.cpp 1. res…...
Android高级开发-APK极致优化
九道工序 1. SVG(Scalable Vector Graphics)可缩放矢量图 使用矢量图代替位图可以减小 APK 的尺寸,因为可以针对不同屏幕密度调整同一文件的大小,而不会降低图像质量。 矢量图首次加载时可能消耗更多的 CPU 资源。之后,二者的内存使用率和…...
Rocketmq--消息驱动
1 MQ简介 1.1 什么是MQ MQ(Message Queue)是一种跨进程的通信机制,用于传递消息。通俗点说,就是一个先进先出的数据结构。 1.2 MQ的应用场景 1.2.1 异步解耦 最常见的一个场景是用户注册后,需要发送注册邮件和短信通…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...
Flask RESTful 示例
目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题: 下面创建一个简单的Flask RESTful API示例。首先,我们需要创建环境,安装必要的依赖,然后…...
智慧医疗能源事业线深度画像分析(上)
引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...
(二)原型模式
原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...
从零实现STL哈希容器:unordered_map/unordered_set封装详解
本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说,直接开始吧! 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...
IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)
文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...
vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
Scrapy-Redis分布式爬虫架构的可扩展性与容错性增强:基于微服务与容器化的解决方案
在大数据时代,海量数据的采集与处理成为企业和研究机构获取信息的关键环节。Scrapy-Redis作为一种经典的分布式爬虫架构,在处理大规模数据抓取任务时展现出强大的能力。然而,随着业务规模的不断扩大和数据抓取需求的日益复杂,传统…...

