当前位置: 首页 > news >正文

TCP/IP协议详解(二)

目录内容
TCP协议的可靠性
TCP的三次握手
TCP的四次挥手
C#中,TCP/IP建立
三次握手和四次挥手常见面试题

在上一篇文章中讲解了TCP/IP的由来以及报文格式,详情请见上一篇文章,现在接着来讲讲TCP/IP的可靠性以及通过代码的实现。
在TCP首部的后面是数据部分,数据部分是可选的,可以有,也可以没有。当一个连接建立和一个连接终止时,双方交换的报文段仅为TCP的报文首部。假如发送方没有数据要发送,也没有使用任何数据的首部来确认收到的数据,例如在处理发送数据超时时,也会发送不带数据的报文段。
**

TCP协议的可靠性

**
主要靠以下几点来进行保障:
(一)应用数据分割成TCP认为最适合发送的数据块。这部分是通过MSS(最大数据包长度)选项来控制的,这种机制被称为协商机制,规定了传输的最大数据块长度。但是,MSS只能出现在SYN报文段中,若服务端不接收客户端的MSS值,则MSS长度定为536字节。通常来讲,MSS值是越大越好,有利于提高网络利用率。
(二)重传机制。设置定时器,等待确认包,如果定时器超时还未收到确认包,则报文重传。
(三)对首部和数据进行校验。
(四)接收端对收到的数据进行排序,然后传输给应用层。
(五)接收端丢弃重复的数据。
(六)TCP提供流量控制,主要是通过滑动窗口来实现流量控制。
经过上一篇文章和以上的讲解,TCP协议的数据帧格式就讲解完毕。
**

TCP的三次握手

**
我们都知道,TCP在建立连接和断开连接时,需要进行三次握手和四次挥手,那么我们可以进行思考,三次握手和四次挥手分别都做了些什么?又是如何进行的呢?
三次握手的过程:
TCP建立连接时,双方需要经过三次握手,具体过程如下:
1、第一次握手:Client端进入SYN_SEND状态,发送一个SYN帧来主动打开传输通道,该帧的SYN标志位被设置为1,同时会带上Client分配好的SN序列号,该SN是根据时间产生的一个随机值,通常情况下每隔4ms会加1。同时,SYN帧还会带一个MSS(最大报文段长度)可选项的值,表示客户端发送出去的最大数据块的长度;
2、第二次握手:Server端在收到SYN帧以后,会进入SYN_RCVD状态,同时返回SYN+ACK帧给Client,主要目的在于通知Client,Server端已收到了SYN消息,现在需要进行确认。Server端发出的SYN+ACK帧的ACK标志位被设置为1,其确认序号AN值被设置为Client端的SN+1;SYN+ACK帧的SYN标志位被设置为1,SN值为Server端生成的SN序号;SYN+ACK帧的MSS表示的是Server端的最大数据长度;
3、第三次握手:Client在收到Server的第二次握手SYN+ACK确认帧之后,首先会将自己的状态从SYN_SENT变为ESTABLISHED,表示自己方向的连接通道已经建立成功,Client可以发送数据到Server端。Client发送ACK帧到Server端,该ACK帧的ACK标志位被设置为1,其确认序号AN值被设置为Server端的SN序列号+1。另外,Client可能会将ACK帧和第一帧要发送的数据,合并到一起发送给Server端;
4、Server端在收到Client的ACK帧之后,会从SYN_RCVD状态进入ESTABLISHED状态,至此,Server端方向的通道连接建立成功,Server端可以发送数据到Client端,TCP的全双工连接建立成功。
在这里插入图片描述

Client和Server完成了三次握手之后,双方就进入了数据传输阶段。数据传输完成后,连接将断开,连接断开的过程需要经过四次挥手。
**

TCP的四次挥手

**
Client端和Server端完成数据通信后,TCP连接开始处于断开的过程,在这个过程中,连接的每个端都能独立地、主动的发起,断开的过程中,TCP协议使用四次挥手操作。
四次挥手具体过程如下:
1、第一次挥手:主动断开方(客户端或者服务端),向对方发送一个FIN结束请求报文,此报文的FIN标志位被设置为1,并且正确设置Sequence Number(序列号)和Acknowledgment Number(确认号)。发送完成后,主动断开方进入FIN_WAIT_1状态,表示主动断开方没有数据要发送给对方,准备关闭连接;
2、第二次挥手:在收到主动断开方发送的FIN断开请求报文后,被动断开方会发送一个ACK响应报文,报文的AN值为主动断开请求方报文的SN+1,该ACK确认报文的含义是:我同意你的连接断开请求。然后,被动断开方进入CLOSE_WAIT(关闭等待)状态,TCP协议服务会通知高层的应用进程,对方向本地方向的连接已经关闭,对方已经没有数据可以发送,若本地还要发送数据给对方,对方依然会接收。被动断开方的CLOSE_WAIT(关闭等待)还要持续一段时间,也就是整个CLOSE_WAIT状态持续的时间。主动断开方在收到ACK报文后,由FIN_WAIT_1转换为FIN_WAIT_2状态;
3、第三次挥手:在发送完ACK报文后,被动断开方还可以继续完成数据发送,等待剩余数据发送完成后,或者CLOSE_WAIT(关闭等待)截至后,被动断开方向主动断开方发送一个FIN+ACK结束响应报文,表示被动断开方的数据已发送完毕,被动断开方进入LAST_ACK状态;
4、第四次挥手:主动断开方在收到FIN+ACK断开响应报文后,还需要进行最后确认,向被动断开方发送一个ACK确认报文,然后进入TIME_WAIT状态,等待超时后最终关闭连接。处于TIME_WAIT状态的主动断开方,在等待2MSL(TCP报文段在网络中最大的存活时间)后,如果期间没有收到其它报文,则证明对方已正常关闭,主动断开方的连接最终关闭。被动断开方在收到主动断开方的最后发送的ACK报文后,最终关闭连接。

在第四次挥手中,为什么是等待2MSL(Maximun Segment Lifetime)呢?
因为2MSL指的是一个TCP报文段在网络中最大的存活时间,2MSL对应于一次消息的来回(一个发送和一个回复)所需的最大时间。如果超过了2MSL,主动断开方都没有收到对方的报文(如FIN报文),则可以推断ACK已经被对方成功接收,此时主动断开方将最终结束自己的TCP连接。所以,TCP的TIME_WAIT状态也称为2MSL状态。
在这里插入图片描述

通过以上讲解的三次握手和四次挥手,一次TCP的连接和断开,至少进行7次通信,可见其成本是很高的。
**

C#中,TCP/IP建立

**
Server端

internal class TCPIPServer{private Socket serverSocket = null;private int serverPort = 3401;#region 用来专门监听等待工作的线程private Thread serverListenThread;#endregionpublic TCPIPServer(){/** AddressFamily.InterNetwork:寻找地址的方式,此时选定的是IPV4地址* SocketType.Stream:数据传输方式,此时选择的是Stream传输,能够将数据准确的进行传输* ProtocolType.Tcp:执行的协议,此时选择的是TCP协议*/serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);IPAddress ipAddress = IPAddress.Any; //IPAddress.Parse(GetLocalAddressIP());//绑定IP地址和端口serverSocket.Bind(new IPEndPoint(ipAddress, serverPort));//设置最多15个排队连接请求serverSocket.Listen(15);serverListenThread = new Thread(ListenConnect);//关闭后台线程serverListenThread.IsBackground = true;serverListenThread.Start();Console.WriteLine("服务端监听中");}private string GetLocalAddressIP(){string localAddressIP = string.Empty;foreach(IPAddress ipAddress in Dns.GetHostEntry(Dns.GetHostName()).AddressList){if(ipAddress.AddressFamily.ToString() == "InterNetwork"){localAddressIP = ipAddress.ToString();}}Console.WriteLine("localAddressIP:" + localAddressIP);return localAddressIP;}private void ListenConnect(){while (true){try{Socket clientSecket = serverSocket.Accept();byte[] buffer = Encoding.Default.GetBytes("服务器连接成功!");clientSecket.Send(buffer);string client = clientSecket.RemoteEndPoint.ToString();Thread clientMsgThread = new Thread(ReceiveMessage);clientMsgThread.IsBackground = true;clientMsgThread.Start(clientSecket);}catch(Exception ex){serverListenThread.Interrupt();Console.WriteLine(ex.Message);}}}/// <summary>/// 提取客户端发送的消息/// </summary>/// <param name="clientSocket"></param>private void ReceiveMessage(object clientSocket){Socket client = clientSocket as Socket;while (true){byte[] readBuffer = new byte[1024 * 1024 * 2];int len = -1;try{len = client.Receive(readBuffer);if(len == 0){string endPointMsg = client.RemoteEndPoint.ToString();Console.WriteLine(string.Format("endPointMsg: {0}", endPointMsg));break;}else{string clientMsg = Encoding.Default.GetString(readBuffer, 0, len);Console.WriteLine($"{DateTime.Now}【接收】{clientMsg}{Environment.NewLine}");}}catch(Exception ex){string endPointMsg = client.RemoteEndPoint.ToString();Console.WriteLine(string.Format("endPointMsg: {0}; Exception:{1}", endPointMsg, ex.Message));break;}}}}

运行结果
在这里插入图片描述

Client端

internal class TCPIPClient{private Socket clientSocket = null;private Thread clientThread = null;public TCPIPClient(){clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream,ProtocolType.Tcp);IPAddress serverIPAddress = IPAddress.Parse(GetLocalAddressIP());clientSocket.Connect(new IPEndPoint(serverIPAddress, 3401));byte[] sendMsg = Encoding.Default.GetBytes("客户端发送消息啦!");clientSocket.Send(sendMsg);clientThread = new Thread(ReceiveServerMessage);clientThread.IsBackground = true;clientThread.Start();}private void ReceiveServerMessage(){while (true){byte[] readBuffer = new byte[1024 * 1024 * 2];int len = -1;try{len = clientSocket.Receive(readBuffer);if(len > 0){string serverMsg = Encoding.Default.GetString(readBuffer, 0, len);Console.WriteLine($"{DateTime.Now}【接收】{serverMsg}{Environment.NewLine}");}else if(len == 0){clientThread.Interrupt();Console.WriteLine($"Client get data len={len}");break;}}catch(Exception ex){Console.WriteLine(ex.Message);break;}}}private string GetLocalAddressIP(){string localAddressIP = string.Empty;foreach (IPAddress ipAddress in Dns.GetHostEntry(Dns.GetHostName()).AddressList){if (ipAddress.AddressFamily.ToString() == "InterNetwork"){localAddressIP = ipAddress.ToString();}}Console.WriteLine("localAddressIP:" + localAddressIP);return localAddressIP;}}

运行结果
在这里插入图片描述

**

三次握手和四次挥手常见面试题

**
(1)为什么关闭连接需要四次挥手,而建立连接只需要三次握手?
因为在关闭连接时,被动断开方在收到主动断开方的FIN结束请求报文时,很有可能数据还没有发送完毕,不能立即关闭连接,被动断开方只能先回复一个ACK响应报文,告诉主动断开方“你发送的FIN报文我收到了,只有等到我所有的数据都发送完毕后,我才能真正的结束,在结束之前,我会向你发送FIN+ACK报文,你先等着”。所以,被动断开方的确认报文,需要拆成两步,故总体就需要四步。
而在建立连接场景中,Server端的应答稍微简单一些。当Server端收到Client端的SYN连接请求报文后,其ACK报文表示对请求报文的应答,SYN报文用来表示服务端的连接已经同步开启,而ACK报文和SYN报文之间,不会有其它报文需要发送,可以将这两者合二为一,可以直接发送SYN+ACK报文。所以,在建立连接时,只需要三次握手。
(2)为什么连接建立的时候是三次握手,可以改成两次握手码?
三次握手完成两个重要的功能:一是双方都做好发送数据的准备,而且双方都知道对方已经准备好了;二是双方完成初始SN序列号的协商,双方的SN序列号在握手过程中被发送和确认。
如果把三次握手改成两次握手,可能发生死锁。两次握手缺少Client端的二次ACK帧确认,假想的TCP建立连接时二次握手,可能如下图所示:
在这里插入图片描述

在假想的TCP建立连接两次握手过程中,Client端发送Server端的SYN请求帧,Server端收到后发送了确认应答SYN+ACK帧。按照两次握手的协定,Server端认为连接已经建立成功,可以开始发送数据帧。这个过程中,如果确认应答SYN+ACK帧在传输过程中丢失,Client端没有收到,Client端将不知道Server端是否准备好了,也不知道Server端的SN序列号,Client端认为连接未建立成功,将忽略Server端发送的任何分组数据,会一直等待Server端SYN+ACK确认应答帧。在Server端发出数据帧后,一直没有收到对应的ACK确认后就会产生超时,重复发送同样的数据帧,从而陷入死锁。
(3)为什么主动断开方在TIME-WAIT状态必须等待2MSL的时间?
因为主动断开方等待2MSL时间,是为了确保主动断开方和被动断开方都能最终关闭。假设网络是不可靠的,被动断开方发送FIN+ACK报文后,主动断开方的ACK响应报文有可能丢失,这时被动断开方处于LAST+ACK状态,由于收不到ACK确认码,被动断开方一直不能进入CLOSED状态。在这种情况下,被动断开方会超时重传FIN+ACK断开响应报文,如果主动断开方在2MSL时间内,收到这个重传的FIN+ACK报文,会重传一次ACK报文,再一次重新启动2MSL计时等待,这样就能确保被动断开方收到ACK报文,确保被动断开方顺利进入CLOSED状态。只有这样,双方都能够确保关闭。反过来,如果主动断开方在发送完ACK响应报文后,不是进入TIME_WAIT状态去等待2MSL时间,而是立即释放连接,则将无法收到被动断开方重传的FIN+ACK报文,所以不会在发送一次ACK确认报文,此时处于LAST_ACK状态的被动断开方,无法正常进入到CLOSED状态。
另一方面,防止“旧连接的已失效的数据报文”出现在新连接中,主动断开方在发送完最后一个ACK报文后,在经过2MSL,才能最终关闭和释放断开。因此,相同端口的TCP新连接,需要在2MSL时间之后,才能够正常建立连接。2MSL时间内,旧连接产生的所有数据报文,都已经从网络中消失了,从而确保了下一个新连接中不会出现旧连接报文请求。
(4)如果已经建立了连接,但是Client端突然出现故障怎么办?
TCP设有一个保活计时器,如果Client端出现故障,Server端不会一直等待,如果一直等待会造成系统资源浪费。Server端每收到一次Client端的数据帧后,Server端的保活计时器会复位。计时器的超时设置时间通常为2小时,若2小时还没有收到Client端的任何数据帧,Server端就会发送一个探测报文段,之后每隔75秒发送一次。若连续发送10个探测报文仍没有反应,Server端就认为Client出现故障,Server端会关闭连接。如果保活计时器的2小时间隔太长,可自行调整TCP连接的保活参数。

相关文章:

TCP/IP协议详解(二)

目录内容 TCP协议的可靠性 TCP的三次握手 TCP的四次挥手 C#中&#xff0c;TCP/IP建立 三次握手和四次挥手常见面试题 在上一篇文章中讲解了TCP/IP的由来以及报文格式&#xff0c;详情请见上一篇文章&#xff0c;现在接着来讲讲TCP/IP的可靠性以及通过代码的实现。 在TCP首部的…...

Linux6.2 ansible 自动化运维工具(机器管理工具)

文章目录 计算机系统5G云计算第一章 LINUX ansible 自动化运维工具&#xff08;机器管理工具&#xff09;一、概述二、ansible 环境安装部署三、ansible 命令行模块1.command 模块2.shell 模块3.cron 模块4.user 模块5.group 模块6.copy 模块7.file 模块8.hostname 模块9.ping …...

前端面试题 —— React (二)

目录 一、React 组件中怎么做事件代理&#xff1f;它的原理是什么&#xff1f; 二、React.Component 和 React.PureComponent 的区别 三、Component, Element, Instance 之间有什么区别和联系&#xff1f; 四、React声明组件有哪几种方法&#xff0c;有什么不同&#xff1f…...

【分享帖】LCD的MCU接口和SPI接口详解

LCD&#xff08;Liquid Crystal Display&#xff09;液晶屏&#xff0c;作为电子产品的重要组成部分&#xff0c;是终端用户与电子产品交互的重要载体。现在市场上的LCD&#xff0c;按照尺寸、功能、接口、用途等分为很多种&#xff0c;本文主要介绍如下两种LCD物理接口&#x…...

【Java】使用@Expose注解和excludeFieldsWithoutExposeAnnotatGson()方法将toJson()过程的部分字段忽略

要在使用 Gson 的 toJson() 方法时忽略 List 中的某些字段&#xff0c;你可以使用 Gson 的 Expose 注解和 excludeFieldsWithoutExposeAnnotation() 方法。 首先&#xff0c;在 List 中的 Bean 类中&#xff0c;使用 Expose 注解标记你想要序列化的字段&#xff1a; public c…...

移动硬盘不显示怎么办?正确解决方式看这里!

移动硬盘为存储带来了很大的方便&#xff0c;在对数据存储时&#xff0c;可做到即插即用&#xff0c;且其体积小、容量大&#xff0c;且比较安全可靠。但在实际的使用中&#xff0c;也会出现各种问题。请看下面2个常见案例。 案例1&#xff1a;“各位朋友&#xff0c;我新买了一…...

MySQL 5.7.39 关于时间精度

前情提要 当EndTime的数据类型为datetime when the end_time’s dataType is datetime; entity.EndTime DateTime.MaxValue; context.Set<T>().Add(entity);当保存 ‘9999-12-31 23:59:59’ 这个值时,发生报错。 A crash has happended in the program when saving ‘…...

宝塔设置云服务器mysql端口转发,实现本地电脑访问云mysql

环境&#xff1a;centos系统使用宝塔面板 实现功能&#xff1a;宝塔设置云服务器mysql端口转发&#xff0c;实现本地电脑访问mysql 1.安装mysql、PHP-7.4.33、phpMyAdmin 5.0 软件商店》搜索 mysql安装即可 软件商店》搜索 PHP安装7.4.33即可&#xff08;只需要勾选快速安装&…...

centos下安装ftp-读取目录列表失败-

1.下载安装ftp服务器端和客户端 #1.安装yum -y install vsftpdyum -y install ftp #2.修改配置文件vim /etc/vsftpd.conflocal_enablesYESwrite_enableYESanonymous_enableYESanon_mkdir_write_enableYES //允许匿名用户在FTP上创建目录anon_upload_enableYES //允许匿名用户…...

0101sub-process /usr/bin/dpkg returned an error code-dpkg-linux问题集

kali linux有段时间没用了&#xff0c;现在有点时间想着继续学习下网络安全&#xff0c;那就升级更新下。 apt-get update && apt-get upgrade等待一段时间后&#xff0c;下载完毕执行安装和更新&#xff0c;更新的过程中报错退出了 问题1 更新kali-themes 需要kali-t…...

流控平台Sentinel搭建和接入教程

流量控制和限流是大型系统必不可少的组成部分&#xff0c;Sentinel是Alibaba提供的一款特别好用的专业工具&#xff0c;属于那种看起来很牛&#xff0c;用起来也很牛的工具&#xff0c;下面记录一下接入的过程。 一&#xff0c;搭建平台 1&#xff0c;下载jar包 地址&#x…...

使用 docker 一键部署 MongoDB

目录 1. 前期准备 2. 导入镜像 3. 部署MongoDB脚本 4. 配置模板文件 5. 部署MongoDB 6. 部署后配置 7. 基本维护 1. 前期准备 新部署前可以从仓库&#xff08;repository&#xff09;下载 MongoDB 镜像&#xff0c;或者从已有部署中的镜像生成文件&#xff1a; # 查看…...

【深度学习】Inst-Inpaint: Instructing to Remove Objects with Diffusion Models,指令式图像修复

论文&#xff1a;https://arxiv.org/abs/2304.03246 code:http://instinpaint.abyildirim.com/ 文章目录 AbstractIntroductionRelated WorkDataset GenerationMethodPS Abstract 图像修复任务是指从图像中擦除不需要的像素&#xff0c;并以语义一致且逼真的方式填充它们。传统…...

创建维基WIKI百科和建立百度百科有何不同?

很多企业有出口业务&#xff0c;想在互联网上开展全球性网络营销&#xff0c;维基百科往往被认为是开展海外营销的第一站。其作用相当于开展国内网络营销的百度百科&#xff0c;经常有些企业给小马识途营销顾问提供的词条内容就是百度百科的内容&#xff0c;可事实上两个平台的…...

Python小红书旋转验证码识别

本周免费接了一个用户的需求&#xff0c;研究了一下小红书旋转验证码。刚开始小瞧了它&#xff0c;觉得它应该没有百度旋转验证码那么难&#xff0c;毕竟图像没有干扰&#xff0c;需要的训练样本就可以很少。然而事情并没有这么简单&#xff0c;所以记录一下。 首先看一下最终…...

ELK搭建

ELK概述 ELK是elasticsearch Logstash Kibana 这种架构的简写。这是一种日志分平台析的架构&#xff0c; Elasticsearch Logstash filebeat Kibana 这种架构增加了一个filebeat模块。filebeat是一个轻量的日志收集代理&#xff0c;用来部署在客户端&#xff0c;优势是消耗…...

webyog最新社区版免费版下载地址

好用的sql管理工具分享&#xff1a; https://github.com/webyog/sqlyog-community/wiki/Downloads webyog最新社区版免费使用下载。从此不用在找mysql的管理工具而烦恼。...

[SQL挖掘机] - 窗口函数 - dense_rank

介绍: dense_rank() 是一种常用的窗口函数&#xff0c;它为结果集中的每一行分配一个密集排名&#xff08;dense rank&#xff09;。这个密集排名基于指定的排序顺序&#xff0c;并且在遇到相同的值时&#xff0c;不会跳过排名。 用法: dense_rank() 函数的语法如下&#xf…...

stable diffusion

一&#xff1a;安装。 stable diffusion 安装和使用全教程 - 知乎 Stable Diffusion安装 - 知乎 环境安装&#xff1a; 1&#xff1a;python 3.10安装。 Download Python | Python.org 切记要安装3.10版本&#xff0c;因为Stable diffusion是用3.10版本编写的&#xff0c;所…...

web3行业有哪些职业发展路径?

Web3 是一个相对较新的概念&#xff0c;因此其职业发展路径也在不断演变。一般来说&#xff0c;Web3 职业发展路径可以分为以下几个方向&#xff1a; 区块链开发工程师&#xff1a;区块链开发工程师需要掌握 Solidity 等语言和智能合约开发技能&#xff0c;负责开发和维护区块…...

谷歌浏览器插件

项目中有时候会用到插件 sync-cookie-extension1.0.0&#xff1a;开发环境同步测试 cookie 至 localhost&#xff0c;便于本地请求服务携带 cookie 参考地址&#xff1a;https://juejin.cn/post/7139354571712757767 里面有源码下载下来&#xff0c;加在到扩展即可使用FeHelp…...

idea大量爆红问题解决

问题描述 在学习和工作中&#xff0c;idea是程序员不可缺少的一个工具&#xff0c;但是突然在有些时候就会出现大量爆红的问题&#xff0c;发现无法跳转&#xff0c;无论是关机重启或者是替换root都无法解决 就是如上所展示的问题&#xff0c;但是程序依然可以启动。 问题解决…...

TDengine 快速体验(Docker 镜像方式)

简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能&#xff0c;本节首先介绍如何通过 Docker 快速体验 TDengine&#xff0c;然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker&#xff0c;请使用 安装包的方式快…...

云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地

借阿里云中企出海大会的东风&#xff0c;以**「云启出海&#xff0c;智联未来&#xff5c;打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办&#xff0c;现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...

Typeerror: cannot read properties of undefined (reading ‘XXX‘)

最近需要在离线机器上运行软件&#xff0c;所以得把软件用docker打包起来&#xff0c;大部分功能都没问题&#xff0c;出了一个奇怪的事情。同样的代码&#xff0c;在本机上用vscode可以运行起来&#xff0c;但是打包之后在docker里出现了问题。使用的是dialog组件&#xff0c;…...

C#中的CLR属性、依赖属性与附加属性

CLR属性的主要特征 封装性&#xff1a; 隐藏字段的实现细节 提供对字段的受控访问 访问控制&#xff1a; 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性&#xff1a; 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑&#xff1a; 可以…...

【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题

【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要&#xff1a; 近期&#xff0c;在使用较新版本的OpenSSH客户端连接老旧SSH服务器时&#xff0c;会遇到 "no matching key exchange method found"​, "n…...

解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用

在工业制造领域&#xff0c;无损检测&#xff08;NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统&#xff0c;以非接触式光学麦克风技术为核心&#xff0c;打破传统检测瓶颈&#xff0c;为半导体、航空航天、汽车制造等行业提供了高灵敏…...

华为OD最新机试真题-数组组成的最小数字-OD统一考试(B卷)

题目描述 给定一个整型数组,请从该数组中选择3个元素 组成最小数字并输出 (如果数组长度小于3,则选择数组中所有元素来组成最小数字)。 输入描述 行用半角逗号分割的字符串记录的整型数组,0<数组长度<= 100,0<整数的取值范围<= 10000。 输出描述 由3个元素组成…...

Linux安全加固:从攻防视角构建系统免疫

Linux安全加固:从攻防视角构建系统免疫 构建坚不可摧的数字堡垒 引言:攻防对抗的新纪元 在日益复杂的网络威胁环境中,Linux系统安全已从被动防御转向主动免疫。2023年全球网络安全报告显示,高级持续性威胁(APT)攻击同比增长65%,平均入侵停留时间缩短至48小时。本章将从…...