TCP原理(全网最详细)
一、确认应答(可靠性机制)
TCP诞生的初衷就是可靠传输
可靠传输是TCP最核心的部分,TCP内部很多机制都是在保证可靠传输(可以理解为发一条消息,上面显示已读未读,可靠传输就是发一条消息我知道对方是否收到)。
确认应答,要针对数据进行编号,然后才能明确,应答报文实在应答那个数据,应对了网络传输的“后发先至”
TCP就引入了“序号”
32位序号:给发送的每一条数据,都进行了编号
32位确认序号:如果当前报文是一个普通的报文。确认序号不生效,但是如果当前报文是一个应答报文,确认序号就表示应答的是哪个普通报文。
报文字节:
由于TCP是面向字节流的,编号的时候,不是按照条编号,而是按照字节来编号。
图中的主机A发送了100字节的数据(一个TCP数据报,长度是1000,序号是1)
应答报文中的确认序号就是1001。应答报文,可以视为只有TCP报头,没有载荷。其中的确认序号字段填写的是1001,意思就是<1001的数据,主机B全部都收到了,接下来A就要从1001开始往后发送。
此时有人就会问,TCP不是传输的字节流呢?怎么传输的数据报呢?
例如在我们的UDP中:
B这边调用一个recv方法:
- 第一次读取的是1111
- 第二次读取的是2222
- 第三次读取的是3333
每次调用recv方法就是从接收缓冲区中取走一个数据,UDP的接受缓冲区,相当于一个链表,里面三个节点,每次都以一个节点为单位进行读取,这就是面向数据报。
在TCP中:
用InputStream.read(buffer)
- byte[1] buffer 读出来的就是 1
- byte[3] buffer 读出来的就是 111
- byte[5] buffer 读出来的就是 11112
- byte[7] buffer 读出来的就是 1111222
TCP的接收缓冲区,就i像一个数组,若干个TCP数据报的载荷会一直追加到这个数组里,这就是面向字节流。
如何区分,一个报文是普通报文还是应答报文呢?
在TCP报头中有6个非常重要的比特位,其中第二个ACK就是表达的应答报文。
- ACK是0表达不是应答报文
- ACK是1表带是应答报文
URG(Urgent):URG标志位占据TCP头部的第13位(最左边的位),用于指示紧急数据。如果URG标志位被设置为1,那么TCP包含的数据被标记为紧急数据,需要被尽快传送和处理。
ACK(Acknowledgment):ACK标志位占据TCP头部的第14位,用于确认对方已经成功接收到了之前发送的数据。当ACK标志位被设置为1时,表示这是一个包含确认信息的TCP报文。
PSH(Push):PSH标志位占据TCP头部的第15位,用于指示接收方应该尽快将数据交给应用程序,而不是等到缓冲区充满或等待定时器触发。
RST(Reset):RST标志位占据TCP头部的第16位,用于重置连接。如果RST标志位被设置为1,它表示连接出现了异常,需要立即关闭,并且后续的数据传输将被终止。
SYN(Synchronize):SYN标志位占据TCP头部的第17位,用于建立连接。当客户端尝试与服务器建立连接时,它会将SYN标志位设置为1,表示请求建立连接。
FIN(Finish):FIN标志位占据TCP头部的第18位,用于关闭连接。当一方希望关闭连接时,它会将FIN标志位设置为1,表示它已经不再发送数据,并且希望进行优雅的连接关闭。
在确认应答的情况下,如果收到了ACK就好办,但是如果没有收到呢?还需要通过其他途径来处理。
二、超时重传(可靠性机制)
确认应答是一种很理想的状态,但是数据开发的过程中很容易出现丢包的情况。
发送请求丢失
ACK丢失
业务数据已经到了主机B,反馈的ACK没有回去,发送方等待了一会之后,就会触发重传。对于发送方来说,无法区分是发送请求丢失还是ACK丢失,因此发送方能做的就是到达一定时间超时重传。
ACK丢失的情况下,进行超时重传,接收方会收到两份相同的数据,这个时候就会涉及到去重。根据序列号,把序列号相同的去除掉。
丢包操作,还有一个超时时间,超时时间具体是多少,在操作系统内核是可以配置的。
第一次丢包,超时时间是 T1
第二次丢包,超时时间是 T2
T2 > T1 这里等待的时间间隔随着时间的推移越来越大,连续两次没发过去,意味着当前单次丢包的概率已经相当大了,很可能是网络上遇到了非常严重的事故,短期内恢复不了,发送的再频繁也没用。超时重传也不会无限制的重传下去,尝试几次之后,仍然无法传送过去,此时就会放弃重传,然后尝试断开重连,如果重连还没连上去,就彻底放弃了。
超时的时间如何确定?
- 最理想的情况下,找到一个最小的时间,保证 “确认应答一定能在这个时间内返回”。
- 但是这个时间的长短,随着网络环境的不同,是有差异的。
- 如果超时时间设的太长,会影响整体的重传效率;
- 如果超时时间设的太短,有可能会频繁发送重复的包;
TCP为了保证无论在任何环境下都能比较高性能的通信,因此会动态计算这个最大超时时间
Linux中(BSD Unix和Windows也是如此),超时以500ms为一个单位进行控制,每次判定超时重发的超时时间都是500ms的整数倍。
如果重发一次之后,仍然得不到应答,等待 2*500ms 后再进行重传。
如果仍然得不到应答,等待 4*500ms 进行重传。依次类推,以指数形式递增。
累计到一定的重传次数,TCP认为网络或者对端主机出现异常,强制关闭连接
确认应答和超时重传是保证TCP可靠性的最核心机制
三、连接管理(可靠性机制)
建立连接-三次握手
当A给B打电话的时候,打电话的时候同样要验证自己一起对方的话筒和自己的听筒是否正常
第一次握手: 刚开始,A 不知道自己和 B 手机的听筒和话筒是否正常,所以 A说"喂,你能听到吗?"
第二次握手: B 听到后,说明 A 的话筒和 B 的听筒正常,但 B 还需进一步检查自己的话筒和 A 的听筒是否正常;同时 B 把 A 话筒正常和自己听筒正常的消息传递给 A;于是 B “我能听到,你呢?”
第三次握手: A 收到 B 的消息后,就证明了 A 听筒正常,B 话筒正常
以上三次握手就保证A、B的听筒和话筒都是正常,也就保证了通话的正常,这就也是类似网络建立连接的三次握手
TCP中真实的建立连接过程:
第一次握手:客户端希望与服务器建立连接,因此它首先向服务器发送一个TCP报文段,其中包含SYN(同步)标志位。这个SYN标志位表示客户端希望建立连接,并在报文段中包含一个初始序列号(ISN),该序列号用于标识客户端发送的数据。
第二次握手:服务器收到客户端的SYN后,会确认客户端的请求。服务器向客户端发送一个TCP报文段,其中包含SYN和ACK(确认)标志位。服务器也会选择自己的初始序列号(ISN)。这个ACK用于确认客户端的SYN,并表示服务器已经准备好建立连接。
第三次握手:客户端收到服务器的SYN-ACK后,会发送一个带有ACK标志位的TCP报文段给服务器。这个ACK用于确认服务器的SYN,并表示客户端也已经准备好建立连接。同时,客户端也会发送自己的初始序列号。
建立连接的过程,相当于通信双方各自给对方发送 SYN,在各自给对方发送给 ACK,只不过中间的 ACK 和 SYN 合二为一了,于是最后就是"三次握手"。
为什么要合并在一起传输?每次报文传输,都会经过一系列的封装分用!分成两个包的代价就会很大。
断开连接-四次挥手
三次握手:双方各自向对方发起建立连接的请求,确保双方都明确知道对已准备好连接。
四次挥手:用于确保双方在终止连接之前完成数据传输,并且都明确知道对方已经准备好关闭连接。
以打电话为例子:
TCP中真实的断开连接过程:
第一次挥手(客户端向服务器发送FIN)
- 客户端决定关闭连接,因此向服务器发送一个TCP报文段,其中包含FIN(Finish)标志位。则合格FIN表示客户端已经完成数据发送,并请求关闭。客户端进入FIN_WAIT1状态。
第二次挥手(服务器回复ACK):
- 服务器收到客户端的FIN后,会发送一个确认ACK数据报作为响应,以确认它已经收到客户端的关闭请求,同时,服务器进入CLOSE_WAIT状态。
第三次挥手(服务器向客户端发送FIN):
- 当服务器也决定关闭连接时,它会向客户端发送一个带有FIN标志位的TCP报文段,表示服务器已经完成数据发送并请求关闭连接。服务器进入LAST_ACK状态。
第四次挥手(客户端回复ACK):
- 客户端收到服务器的FIN后,会回复一个确认ACK,表示客户端已收到服务器的关闭请求,此时客户端进入TIME_WAIT状态,等待一段时间(通常是两倍的最大寿命,以确保服务器收到ACK),然后才最终关闭连接。
在客户端的TIME_WAIT状态结束后,连接关闭。服务器在发送FIN后等待一段时间,确认客户端收到FIN的ACK之后,连接终止。
四次挥手三次挥完不行呢?
通常是不可以的,即:上述2、3为什么没有合并在一起?
因为中间两次操作时机不一样,ACK是收到FIN之后立即由操作系统内核返回的数据报,告诉客户端收到了关闭的消息,而FIN是应用程序处理完接受缓冲区的数据之后,调用close方法触发的。
但是若TCP还有 延时应答和捎带应答 机制,就可以三次挥完。
图中有三部分信息:
- 三次握手和四次挥手中间数据传输流程
- 三次握手四次挥手过程中TCP状态转换
- 每个过程涉及到的socket.api
TCP的状态:
CLOSED(关闭):初始状态,表示TCP连接未建立。在CLOSED状态下,不进行数据传输或通信。
LISTEN(监听):在服务器端,当服务器准备好接受客户端连接请求时,它会进入LISTEN状态。服务器等待客户端的连接请求,一旦收到连接请求,将进入ESTABLISHED状态。
SYN_SENT(同步已发送):客户端在尝试与服务器建立连接时,会进入SYN_SENT状态。在这个状态下,客户端已发送一个带有SYN标志的连接请求,并等待服务器的确认。
SYN_RECEIVED(同步已接收):服务器在收到客户端的连接请求后,会进入SYN_RECEIVED状态,表示已接收客户端的连接请求,准备好建立连接。服务器会回复一个带有SYN和ACK标志的数据包作为确认。
ESTABLISHED(已建立):连接已经建立,双方可以进行数据传输。在这个状态下,数据可以在客户端和服务器之间自由传输。
FIN_WAIT_1(等待对方的结束请求第一阶段):当一方(通常是客户端)决定关闭连接时,它会进入FIN_WAIT_1状态,并发送一个带有FIN标志的数据包,表示它不再发送数据。
FIN_WAIT_2(等待对方的结束请求第二阶段):在FIN_WAIT_1状态之后,如果对方(通常是服务器)也决定关闭连接,它会发送一个带有FIN标志的数据包作为确认,连接进入FIN_WAIT_2状态。
TIME_WAIT(等待时间):连接已经被双方关闭,但为了确保所有的数据包都被完全传递和处理,连接会进入TIME_WAIT状态一段时间。这个状态通常持续2倍的最大报文段寿命(Maximum Segment Lifetime,MSL)时间。
CLOSING(关闭中):表示连接的一方已经发送了FIN标志,但还没有收到对方的确认,所以连接进入CLOSING状态,等待最后的确认。
CLOSE_WAIT(等待关闭):表示连接的一方已经收到对方发送的FIN标志,并进入CLOSE_WAIT状态,等待应用程序处理完所有数据后进行连接关闭。
LAST_ACK(最后确认):在一方发送了FIN标志后,如果另一方也发送了FIN并进入CLOSING状态,那么它会进入LAST_ACK状态,等待最后的确认。
UNKNOWN(未知):在某些情况下,连接状态可能无法明确定义,或者出现异常情况时可能处于UNKNOWN状态。
四、滑动窗口(效率机制)
刚才我们讨论了确认应答策略,对每一个发送的数据段,都要给ACK确认应答,收到ACK后再发下一个数据报,这样会有一个很大的缺点,没法送一个数据报就需要一次请确认应答,才能发送下一个数据报,这样会导致性能比较差,发送时间增长。
可靠性和效率是冲突的,保证可靠性肯定会影响到效率。
TCP在可靠性的前提下,尽可能的提高效率
提高效率的机制,本质就是把等待ACK的时间重叠起来,减少等待时间,就相当提高效率
每次传输的时候都需要等待ACk,收到ACK在发送下一条数据
不再是一次发送一条等待一条,而是一次发送一批,等待一批ACK
窗口大小:再不等待的前提下,最多一次发送N条数据(N就是窗口大小)
这里的N越大,则同时批发数量就会越多,传输效率就会越高!但是N不是越大越好
发送一批数据会不会乱序?
在传输数据的时候很有可能出现“后发先至”的问题,但是TCP就会在接收缓冲区里,按照序号进行排序,保证顺序。
其中灰色的一块一块的区域就是一个TCP数据报,白色的区域就是要批量发送的,图中发送了 1001-2000 2001-3000 3001-4000 4001-5000 在针对这四个数据报,等待 ACK ,当2001ACK回到A的时候,此时1001-2000这个数据就已经被对方收到了,就可以发送5001-6000这个数据了。
每次收到一个ACK,这里的窗口,都会对应向后移动(继续发后续的数据)
如果出现丢包如何进行重传?
情况一:数据报到达了,但是ACK丢了
如果 1001 丢了,2001 到了,此时对于 A 来说,就知道 1-1000 这个数据也是到了的,最后一个会覆盖前一个!
情况二:数据报丢了
数据报丢了,就需要重传,但是什么时候重传?
如上主机A发了半天之后,法案先好几个连续的1001,就明白1001-2000这个数据可能丢失了,接下来就会重传这个数据!此处的原则就是哪条丢失就重传那条数据,已经重传的数据就不需要重传,不必重复传输!快熟重传(不是重传的有多快,而是没有多余的冗余动作)
滑动窗口能提高效率,指的是相比于没有滑动窗口,普通的确认应答。但是如果和无可靠性的传输相比(UDP),效率还是要差一些。与其说它是提高效率,不如说它是在补救低效率
五、流量控制(可靠性机制)
- 本质就是对滑动窗口的约束
滑动窗口,窗口越大,发送速率就会越快!流量控制,就是针对发送速率进行制约(维持可靠性)。
整体的传输速率 = 发送速率 & 接收速率
如果发送速率>接受速率,这个时候继续提高发送速率,就不能提高整体效率,反而会因为接收方的丢包,触发多次重传,反而降低效率。
要做的是,让发送速率和接受速率相当
发送速率:发送数据的时候窗口大小,用于衡量发送速率
接受速率如何衡量?
图中圈出来的部分操作的快慢就是衡量接收速率快慢的(和应用程序代码相关)
流量控制,就是通过解说缓冲区剩余空间大小来作为下一次发送的时候窗口大小
接收方如何把接收缓冲区剩余的空间告诉发送方呢?
可以在ACK这个报文中带上这个信息
当前是 ACK 报文的时候会生效,这个窗口大小,就表示了接收缓冲区的剩余空间大小,根据这个大小,就可以进一步的影响到发送速率了
16位表示的最大数值 64 KB 是否意味着窗口大小最大就是 64 KB 呢?
不是!我们可以有选项,也可以没有,可以有一个,也可以有多个,这里有一个特殊的字段,窗口扩大因子~,窗口扩大因子可以是2,可以是4,可以是任何数,相乘即可,如果没有窗口扩大因子,默认是1。
六、拥塞控制(可靠性机制)
- 流量控制,站在接收方的角度,来控制发送速率,但是整体的传输,其实不光有发送方和接收方,还有中间一系列用来转发的设备!
控制A发的快慢,不仅要考虑到B的接受能力1,也要考虑到中间设备的转发能力!
衡量B的接受能力,是用B的接收缓冲区的剩余空间大小
想要衡量中间的设备,咋办?
- 中间的设备都有几个?
- 中间的设备各个参数是啥?
- 两次传输,经历的中间设备是否相同?
对于拥塞控制,采取的方法就是实验,通过实验的方式,找到一个和舍得窗口大小!
- 刚开始按照小窗口来发送
- 如果不丢包,说明网络中间环境比较通常,就可以提高发送窗口大小
- 放大到一定程度,速率已经比较快,网络上就容易出现拥堵,当发送方发现丢包之后,就减小发送的窗口。
反复测试2-3次,这个过程就会达到一个动态平衡
- 发送的速率不快不慢,接近能承载的极限
- 同时还可以尽量减少丢包
- 还能适应网络环境的动态变化
流量控制 和 拥塞控制 都是通过控制窗口大小,来制约发送方的发送速率的,在保证可靠性的前提下,尽量提高一下发送的速度;都能影响发送方滑动窗口大小!最终的滑动窗口大小,就取决于流量控制和拥塞控制的窗口的“最小值”
- 如果是拥塞控制的窗口大,流量控制的窗口小,中间的节点转发能力强,接收端的代码,处理的慢。
- 如果是拥塞控制的窗口小,流量控制的窗口大,中间的节点转发能力弱,接收端的代码,处理的快。
其中拥塞控制的窗口大小是发送方自己做实验做出来的,流量控制的窗口大小是接收方通过接收缓冲区剩余空间大小,通过 ACK 报文的报头,返回给发送方的。最终发送方下一次发送窗口的大小,就是通过这两个值的较小值来确定的。
上述测试是定性测试,如果是定量测试呢?
初始时候,拥塞窗口,从一个很小的数字开始,指数增长~(慢开始),刚开始的时候网络环境是否拥堵我们不知道!先拿一个小的速率发送,是稳健的做法!如果窗口大小到达阈值之后,就不再指数增长了,变成了线性增长。当线性增长达到一定程度之后,此时就可能丢包,这个时候直接把窗口大小回归到一个特别小的窗口,重复上述的指数增长 / 线性增长的过程,同时,会把刚才线性增长的阈值进行调整。
七、延时应答(效率机制)
- 让流量控制别限制太强
也是一个用来提高效率的机制,延时应答则是让窗口能大一些!在流量控制中,通过ACK告知对方,窗口大小(接收缓冲区的空余空间)是多少合适
在这个等待的时间中,应用程序不停的在消费接收缓冲区(如果立即返回ACK,可能缓冲区的剩余空间是5kb,但是稍等一会,应用程序就可能去走一些数据,缓冲区剩余的空间可能就是50kb或者更多)
这种发送方式是滑动窗口来发送的,发送方是在批量发送数据,所以不会对发送方等待时间造成很大影响,整体影响不大
在接收缓冲区少了一个 1001 应答报文,在延时应答的机制下,ACK 不一定要和发送的数据报一一对应,少点也可以,毕竟 2001 涵盖了 1001
八、捎带应答(效率机制)
在延迟应答的基础上,我们发现,很多情况下,客户端服务器在应用层也是“一发一收”的,意味着客户端给服务器说“How are you”,服务器也会给客户端回一个“Fine,thank you”,那么这个时候ACK就可以搭顺风车,和服务器回应的“Fine,thank you”一同发给客户端
正常情况下,ACK是收到请求之后,内核立即返回的;响应数据,则是应用程序代码发送的,所以他们是出于不同时机发生的,不同的时机,就不能把上个ACK和下一个响应报文合并。但是上面的延时应答,延时一会就可能和返回响应时间重合,一起发送。
所以在延时应答和捎带应答的条件下,四次挥手就可以合并,变成三次挥手
九、面向字节流(其他)
面向字节流,指的是读写载荷数据的时候,是按照“字节流”的方式来读取的。TCP数据报,本身仍然是一个一个数据报这样的方法来传输的。
此时,应用程序,在读取数据的时候,就可以很灵活的进行,可以一次读取M个字节,分N次来读。
面向字节流的最核心问题:粘包问题!
- 如果一个TCP连接,里面就只传了一个应用层数据报,这个时候就不会粘包(短连接)、
- 如果一个TCP连接,里面传输多个应用层数据报,这个时候就容易区分不清,从哪到哪是一个完整的应用层数据
上述图文中,这些数据都进入了接收缓冲区,接收方也就区分不了,这些数据是来自于几个应用层数据报,也区分不了从哪到哪是一个应用层数据报!
粘包问题解决方案:
- 使用分隔符
- 约定长度
- 自定义应用层协议:设计应用层协议时,可以考虑使用一些高级的协议来处理粘包问题,例如HTTP、WebSocket等。这些协议通常具有消息头和消息体的结构,以便更容易地解析消息。
十、异常处理(其他)
主机关机(按照固定程序关机)
按照程序关机,会先杀死所有用户进程
杀死进程=>释放进程PCB=>是访问文件描述表上对应的文件资源(相当于调用close)
这个时候就会触发FIN,开启四次挥手的流程。
如果挥手完成,继续关机就没有问题,但是如果挥手没有结束就直接关机,对端会重传FIN若干次,当任没有回应,也就放弃,单方面解除。
程序奔溃
和上面差不多的,程序正常关闭,还是异常奔溃,都会释放PCB,都会释放文件描述表
也还是会四次挥手(虽然进程没了,但是本身TCP连接也是内核负责的,内核任然会继续完成后续需的挥手操作)
主机掉电(突然断电)
突然断电,就会来不及挥手
- 接收方断电,对方尝试发送数据,发现没有ACK,尝试重传,几次后,没有ACK,发送方尝试重新建立连接,如果还是建立不成功,认为当前网络出现严重问题,也自然的放弃。
- 发送方断电,接收方就等待发送方发送数据,由于发送方掉电,这个数据发不过来,接收方不知道是对方没发还是对方出了问题,如果接收方一段时间没有接收到数据,就会定期给发送方发送心跳包,接收方给发送方发送一个特殊的报文(ping),对方返回一个特殊的报文(pong),如果这个东西有了,就认为对方是正常的状态,如果 ping 没有回应的 pong ,就认为对方挂了。
“心跳包” => 1. 周期性的 2. 判定对方是否存活的
网线断开
和主机掉电相同
扩展:什么时候使用UDP什么时候使用TCP?
- 如果需要关注可靠性传输,优先考虑 TCP
- 如果传输的单个数据报比较大(UDP 报文上限是 64kb)优先考虑 TCP
- 使用 UDP,对于可靠性传输要求不高,但是对于性能要求很高(同一个机房内部的主机之间通信,网络环境简单,宽带充裕,并且又希望主机间通信能够足够快)
- 如果是需要进行 “广播” ,优先考虑 UDP(一个发送方,N 个接收方)(TCP 广播就需要在应用层打开多个连接的方式来实现…)
相关文章:

TCP原理(全网最详细)
一、确认应答(可靠性机制) TCP诞生的初衷就是可靠传输 可靠传输是TCP最核心的部分,TCP内部很多机制都是在保证可靠传输(可以理解为发一条消息,上面显示已读未读,可靠传输就是发一条消息我知道对方是否收到…...

react 初级基础
react基本使用 项目创建 项目的创建命令 npx create-react-app react-basic创建一个基本元素进行渲染 // 1 导入react 和 react-dom import React from "react"; import ReactDOM from "react-dom";// 2 创建 react 元素 React提供了创建元素的api Rea…...

linux学习书籍推荐
《Linux程序设计(第4版)》,Neil Matthew和Richard Stones编写。这本书是Linux/UNIX专家编写的,详细介绍了Linux系统以及其他UNIX风格的操作系统上的程序开发,包括标准Linux C语言函数库和各种由Linux或UNIX标准指定的工…...

LeetCode 428. Serialize and Deserialize N-ary Tree【树,BFS,DFS】困难
本文属于「征服LeetCode」系列文章之一,这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁,本系列将至少持续到刷完所有无锁题之日为止;由于LeetCode还在不断地创建新题,本系列的终止日期可能是永远。在这一系列刷题文章…...

javascript | 变量、函数、属性的命名规则
javascript标识符的命名规则 变量、函数、属性的名字、或者函数的参数,都可称为标识符。标识符可以是按照下列格式规则组合起来的一个或者多个字符。 第一个字符必须是一个字母、下划线_、或美元符号$。数字不可以作为标识符的首字符。其他字符可以是数字、字母、…...

手写Ribbon基本原理
本文已收录于专栏 《中间件合集》 目录 概念说明什么是RibbonRibbon和Nginx负载均衡的区别 工作流程代码实现RibbonSDK发送请求端引入RibbonSDK和Nacos的依赖配置文件中填写负载均衡策略调用代码 接收请求端执行效果发送请求端接收请求端 总结提升 概念说明 什么是Ribbon Ribb…...

k8s集群中ETCD备份和恢复
文章目录 [toc]一、etcd 概述二、安装etcdctl工具三、kubeadm部署方式部署1)备份2)恢复四、定时备份 五、二进制部署备份1)备份2)恢复1、停止apiserver和etcd2、etcd_1恢复3、etcd_2恢复4、etcd_3恢复5、启动etcd和apiserver6、检…...

node版本问题
服务器下载下来的vue项目启动出现下列问题 npm ERR! path E:\vueEnv\app\node_modules\node-sass npm ERR! command failed npm ERR! command C:\Windows\system32\cmd.exe /d /s /c node scripts/build.js npm ERR! Building: C:\Program Files\nodejs\node.exe E:\vueEnv\ap…...

四)Stable Diffussion使用教程:图生图
这一篇来说说图生图。 除了文生图之外,SD常用的还有图生图模式。 图生图,顾名思义就是使用一张图去让AI生成自己喜欢的另一张图。 有时候我们有一张喜欢的图,但是希望换一种颜色方案,这时就可以通过图生图的方式去实现了&#…...

yolov7简化yaml配置文件
yolov7代码结构简单,效果还好,但是动辄超过70几个模块的配置文件对于想要对网络进行魔改的朋友还是不怎么友好的,使用最小的tiny也有77个模块 代码的整体结构简单,直接将ELAN结构化写成一个类就能像yolov5一样仅仅只有20几个模块&…...

pprof火焰图性能优化
pprof火焰图性能优化 火焰图(flame graph)是性能分析的利器,在go1.1之前的版本我们需要借助go-torch生成,在go1.1后go tool pprof集成了此功能,今天就来说说如何使用其进行性能优化 在你启动http server的地方直接加入导入: _ “net/http/pprof” 获取…...

Greenplum 查找数据目录占用最大的表
背景 社区中某同学提出问题: 某环境磁盘占用空间较大,于是想找到数据目录占用最大的表。使用常规查询找不出来,于是到数据目录下分析filenode,找到3个filenode占了400G。然而根据filenode从pg_class中确找不到对应的relfilenode。…...

Java 基于 SpringBoot 的酒店管理系统,附源码和数据库
博主介绍:✌程序员徐师兄、7年大厂程序员经历。全网粉丝30W,Csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 文章目录 一、前言介绍二、系统结构三、系统详细实现3.1用户信息管理3.2会员信息管理3.3客房信息管理3.4收藏…...

LinkedList(4):多线程LinkedList 不安全情况
多线程不安全演示,线程越多,现象越明显,这边只启了四个线程。 package com.example.demo;import java.util.LinkedList; import java.util.UUID;public class LInkedListThread {public static void main(String[] args) {final LinkedList&…...

3D印刷电路板在线渲染查看工具
从概念上讲,这是有道理的,因为PCB印制电路板上的走线从一个连接到下一个连接的路线基本上是平面的。 然而,我们生活在一个 3 维世界中,能够以这种方式可视化电路以及相应的组件,对于设计过程很有帮助。本文将介绍KiCad…...

【mysql】出现 slow sql 问题及建议
文章目录 1. SQL 执行什么情况下会变慢?2. 影响 SQL 语句执行效率的主要因素有哪些?3. 慢 SQL 是如何拖垮数据库的?4. 最佳实践建议 1. SQL 执行什么情况下会变慢? ● 数据量增加:数据库中的数据量可能会逐渐增加&…...

element树形筛选
<el-inputv-model"projectName"placeholder"请输入名称"clearablemaxlength"10"clear"clearTree" /> <el-divider /> <el-treeref"tree"class"filter-tree":data"treeList":props"…...

打字侠:一款专业的中文打字网站
打字侠第一个正式版发布啦!!! 虽然离期望的样子还有一段路要走,不过能看到它正式发布,我还是很激动哟! 打字侠是一款面向中学生和大学生的在线打字软件,它通过合理的课程设计和精美的图形界面帮…...

C++ std::default_random_engine的使用
使用std::default_random_engine可生成不同分布的随机数,下面使用实例来说明其使用。 随机生成0-1间的实数 //利用当前时间生成的种子,可保证每次生成的值都不一样 unsigned seed std::chrono::system_clock::now().time_since_epoch().count(); std:…...

软件设计模式(二):工厂、门面、调停者和装饰器模式
前言 在这篇文章中,荔枝将会梳理软件设计模式中的四种:工厂模式、Facade模式、Mediator模式和装饰器Decorator模式。其中比较重要的就是工厂模式和装饰器模式,工厂模式在开发中使用的频数比较高。希望荔枝的这篇文章能讲清楚哈哈哈哈…...

pdf文件签名的问题解决
今天解决冲突的jar,结果出现下面的问题 java.lang.IllegalAccessError: tried to access method org.bouncycastle.asn1.DERNull.<init>()V from class com.itextpdf.text.pdf.security.PdfPKCS7at com.itextpdf.text.pdf.security.PdfPKCS7.getEncodedPKCS7…...

Node.js安装使用
目录 一、安装 Node.js二、环境变量配置三、npm常用命令 Node.js 是一个强大的运行时环境,它使您能够在服务器端运行 JavaScript 代码。它非常流行,用于构建 Web 应用程序、API 和各种后端服务。 一、安装 Node.js 1、访问 Node.js 官方网站。 在主页上…...

sql:SQL优化知识点记录(七)
(1)索引优化5 (2)索引优化6 (3)索引优化7 查询*, 百分号加右边,否则索引会失效 没建立索引之前都是全表扫描 没建立索引 建立索引: 建立索引 id是主键,他也…...

机器学习:基于梯度下降算法的线性拟合实现和原理解析
机器学习:基于梯度下降算法的线性拟合实现和原理解析 线性拟合梯度下降算法步骤算法实现数据可视化(动态展示)应用示例 当我们需要寻找数据中的趋势、模式或关系时,线性拟合和梯度下降是两个强大的工具。这两个概念在统计学、机器…...

关键点数据增强
1.关键点数据增强 # 关键点数据增强 from PIL import Image, ImageDraw import random import json from pathlib import Path# 创建一个黑色背景图像 width, height 5000, 5000 # 图像宽度和高度 background_color (0, 0, 0) # 黑色填充# 随机分布图像 num_images 1 # …...

最小化安装移动云大云操作系统--BCLinux-for-Euler-22.10-everything-x86_64-230316版
CentOS 结束技术支持,转为RHEL的前置stream版本后,国内开源Linux服务器OS生态转向了开源龙蜥和开源欧拉两大开源社区,对应衍生出了一系列商用Linux服务器系统。BCLinux-for-Euler-22.10是中国移动基于开源欧拉操作系统22.03社区版本深度定制的…...

003传统图机器学习、图特征工程
文章目录 一. 人工特征工程、连接特征二. 在节点层面对连接特征进行特征提取三. 在连接层面对连接特征进行特征提取四. 在全图层面对连接特征进行特征提取 一. 人工特征工程、连接特征 节点、连接、子图、全图都有各自的属性特征, 属性特征一般是多模态的。除属性特…...

Apache Tomcat 漏洞复现
文章目录 Apache Tomcat 漏洞复现1. Tomcat7 弱密码和后端 Getshell 漏洞1.1 漏洞描述1.2 漏洞复现1.3 漏洞利用1.3.1 jsp小马1.3.2 jsp大马 1.4 安全加固 2. Aapache Tomcat AJP任意文件读取/包含漏洞2.1 漏洞描述2.1 漏洞复现2.2 漏洞利用工具2.4 修复建议 3. 通过 PUT 方法的…...

Oracle-常用权限-完整版
-- 创建用户 create user TCK identified by oracle; -- 赋权 grant connect,resource to TCK; -- 删除权限 revoke select any table from TCK -- 删除用户 CASCADE(用户下的数据级联删除) drop user TCK CASCADE -- 查询权限列表 select * from user_role_privs; select * fr…...

jenkins 发布job切换不同的jdk版本/ maven版本
1. 技术要求 因为有个新的项目需要使用jdk17 而旧的项目需要jdk1.8 这就需要jenkins在发布项目的时候可以指定jdk版本 2. 解决 jenkins全局工具配置页面 配置新的jdk 路径 系统管理-> 全局工具配置 如上新增个jdk 名称叫 jdk-17 然后配置jdk-17的根路径即可(这…...