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

【Linux-网络】从逻辑寻址到物理传输:解构IP协议与ARP协议的跨层协作

52bc67966cad45eda96494d9b411954d.png

🎬 个人主页:谁在夜里看海.

📖 个人专栏:《C++系列》《Linux系列》《算法系列》

⛰️ 道阻且长,行则将至


目录

📚前言

📖 IP地址的组成

🔖IPv4

🔖IPv6

📚 一、IP协议(网络层)

📖 1. 报头格式

📖 2. 网段划分

📖 3. 公网&私有IP

📖 4. 路由选择

🔖原理

🔖类型

📚二、ARP协议(数据链路层)

📖 1. 以太网

📖 2. ARP协议

🔖格式


 

📚前言

上一篇文章我们详细介绍了TCP/UDP协议。当数据在应用层完成编写后,传输层会接收到这些数据并进行进一步封装,添加源端口号、目的端口号等信息,以确保数据包能够正确地交付给目标主机上的相应进程进行处理。今天,我们要介绍的IP协议,主要解决的是数据包如何从一台主机传输到另一台主机的问题。

理解IP协议之前,我们需要清楚一个基础概念:什么是IP地址。

IP地址(Internet Protocol Address,互联网协议地址)是分配给网络中每一台设备的唯一标识符,用于计算机在网络中定位和识别设备。有了IP地址,就可以在网络中定位目标主机,传输数据了。(并不严谨)

上述说法是比较笼统的,在具体应用中,IP地址并非唯一标识设备,也无法仅通过IP地址完成数据的传输,原因之一是,网络中设备数量太过庞大,IP地址数量不足:

📖 IP地址的组成

IP地址主要分为两种版本:

① IPv4地址;② Ipv6地址

🔖IPv4

IPv4是一个32位的二进制数字,即由4个字节组成,每个字节表示一个0到255之间的整数,以“点分十进制”书写。例如:192.168.1.1

因此IPv4支持大约43亿个(2^32)独立地址,看似很大,但由于互联网设备的爆发式增长,IPv4已近乎枯竭。

面对资源枯竭的一个解决办法是,改用地址范围更大的IPv6

🔖IPv6

IPv6地址是一个128位的二进制数字,由16个字节组成,划分为八组十六进制数字,每组之间用冒号(:)分隔,例如:2001:0db8:85a3:0000:0000:8a2e:0370:7334

IPv6提供了340万亿个地址(2^128),这一数量远远超过了IPv4的地址数量,能够满足未来互联网设备的需求。 

但是地址版本替换是一个很麻烦的事情, 面临版本不兼容、设备升级、网络配置等多方面的挑战,IPv4到IPv6的过渡是一个漫长且复杂的过程,需要协调各国和各地区的网络运营商、硬件厂商、软件供应商等,分阶段逐步过渡。

应对上述问题,下面我们会介绍到划分方案、私有IP等概念。 

📚 一、IP协议(网络层)

📖 1. 报头格式

在网络层,我们通过IP协议完成数据的封装与转发,与TCP/UDP协议一样,IP协议会给数据包添加对应的IP报头,下面是IP协议的报头格式:

下面我们分别对各个字段进行介绍:

① 版本:该字段指定了IP协议的版本。IPv4的值为4,IPv6的值为6

② 首部长度:该字段指示IP报头的实际长度(单位是32位字,即4字节)。默认情况下,IHL的值为5,表示IP报头的长度为5个32位字(即20字节)

❓为什么需要首部长度字段?

✅因为IP报头和TCP报头一样,存在选项字段,即报头总长不定,需要明确标注。

❓为什么单位是32位(4字节)

✅因为报头的字段基本以32位为一组(源IP地址、目的IP地址都是32位),由此我们也可得知,选项字段也必须以32位为一组。

③ 类型服务:该字段用于提供服务质量(QoS)控制。3位优先权字段(已经弃用), 4位TOS字段, 和1位保留字段(必须置为0)。4位 TOS分别表示: 最小延时, 最大吞吐量, 最高可靠性, 最小成本。这四者相互冲突, 只能选择一个。对于 ssh/telne t这样的应用程序, 最小延时比较重要; 对于 ftp 这样的程序, 最大吞吐量比较重要。

④ 总长度:该字段指示整个IP数据包的总长度,包括头部和数据部分。单位是1字节,最大值为65535字节(2^16),表示总长度最大约为64k字节。

⑤ 标识:在IP数据包分片时,这个字段为所有分片提供一个唯一标识符。每个分片都包含相同的标识符,以便接收方将它们正确地组合在一起。

⑥ 标志:标志字段的作用是指示数据包是否允许分片。它包含3位:

第1位(保留,通常为0)

第2位:Don't Fragment (DF),如果该位为1,则指示数据包不能分片。

第3位:More Fragments (MF),如果该位为1,则说明数据包后面还有更多的分片。

⑦ 片偏移:该字段表示当前分片相对于原始数据包的偏移量。单位为8字节(64位),如果偏移量为1,则表示当前分片从第9个字节开始。

🔖分片

由于在网络中存在最大传输单元(MTU),当数据包的长度大于当前网络的最大传输单元时,需要对数据包分片,以符合传输限制。分片后肯定要对数据进行重组,将数据包还原,然而我们怎么知道数据片原来属于哪个数据包呢,就要通过标识字段。我们在重组数据包时,要确保数据片的顺序正确,这就要通过片偏移字段来完成。

数据包分片后,每个片段都会拥有独立的IP报头,作为独立的IP数据包来传输,通过标识字段、分片偏移量、分片标志这些字段内容,接收端能够识别哪些分片属于同一个数据包,并在收到所有片段后将它们重新组合成完整的数据包

⑧ 生活时间:TTL字段的目的是限制数据包在网络中的生命时间。每经过一个路由器,TTL值就减1,直到TTL为0时,数据包会被丢弃。TTL字段的目的是防止数据包在网络中无限循环

⑨ 协议:用于指示数据包的上层协议。6表示TCP协议;17表示UDP协议;1表示ICMP协议

⑩ 头部校验和:该字段用于检测IP头部在传输过程中是否发生了错误。接收方通过计算报头的校验和来检查数据的完整性。 

⑪ 源IP地址:包含发送方的IP地址,用于标识数据包的来源。

⑫ 目的IP地址:包含接收方的IP地址,用于指示数据包的目的地。

⑬ 选项:选项字段是可选的,包含一些额外的控制信息,例如时间戳、路由记录等。

📖 2. 网段划分

IP地址的分配并不是随意的,而是遵循一定的规则和结构。这种规则主要体现在网段划分上。IP地址分为两个部分,网络号和主机号。

为了方便网络寻址和设备管理,我们将网络上的设备归类为一个个网段中,位于同一个网段下的设备拥有相同的网络号,在网段内部,通过主机号区分每个设备。然而手动分配主机号会相当麻烦,于是有一种技术叫做 DHCP , 能够自动的给子网内新增主机节点分配IP地址, 避免了手动管理IP的不便。一般的路由器都带有DHCP功能,因此路由器也可以看做一个DHCP服务器。

❓问题来了,网络号和主机号该如何进行划分呢,如果随意划分,既不利于网络中的IP寻址,也不利于IP地址的分配管理,于是需要将划分规范化。下面是一种划分网络号和主机号的方案, 把所有IP 地址分为五类:

A类 0.0.0.0到127.255.255.255;

B类 128.0.0.0到191.255.255.255;

B类 128.0.0.0到191.255.255.255;

D类 224.0.0.0到239.255.255.255;

E类 240.0.0.0到247.255.255.255 。

⚠️但是这种划分方式会造成一个问题,就是IP地址的大量浪费。

在这种划分方式中,主机号位数越多,同一网段下支持的设备数量就越多,但同时网段数量就越少,因此我们希望主机号和网络号的位数趋于合理,同时满足设备数量与网段数量的需求。在实际使用中,大多数组织都申请B类网络地址, 导致B类地址很快就 分配完了, 而A类存在大量地址浪费,这是我们不愿意看到的。

✅针对这种情况提出了新的划分方案, 称为CIDR(Classless Interdomain Routing):

引入一个额外的子网掩码(subnet mask)来区分网络号和主机号,子网掩码也是一个32位的正整数,将IP地址与子网掩码进行按位与操作,得到的结果就是网络号。有了子网掩码,我们就可以依据现实情况,动态调整网段可容纳的设备数量。这样一来,大大提升了IP地址的使用效率。

例如:IP地址为 140.252.10.68,子网掩码为 255.255.255.0 时,网络号为 140.252.20.0,子网地址范围为 140.252.20.0 ~ 140.252.20.255。

可见,IP地址与子网掩码做与运算可以得到网络号,主机号从全0到全1就是子网的地址范围;IP地址和子网掩码还有一种更简洁的表示方法,例如140.252.20.68/24,表示IP地址为140.252.20.68, 子网掩码的高 24位是1,也就是255.255.255.0。

🔖下面有几个特殊的IP地址

① 网络号:将IP地址中的主机地址全部设为0, 就成为了网络号, 代表这个局域网;

② 广播地址:将IP地址中的主机地址全部设为1, 就成为了广播地址, 用于给同一个链路中相互连接的所有主机发送数 据包;

③ 127.0.0.1:127.*的IP地址用于本机环回(loop back)测试,通常为127.0.0.1。

📖 3. 公网&私有IP

我们上面提到,IPv4的IP数量不能满足现如今大量网络设备的需求,针对这一问题,使用私有IP是一个很好的办法。如果一个组织内部组建局域网,IP地址只用于局域网内的通信,而不直接连到Internet上,就可以使用私有IP,私有IP独立于公网IP,不同局域网内也可以使用相同的私有IP,这样一来,极大缓解了IP地址不足的问题,因为我们不需要给每一个设备都分配公网IP了

但是私有IP的分配也不是随意的,我们需要将私有IP与公有IP区分开来,私有IP和公有IP我们需要一目了然:如果是私有IP,就可以直接在局域网中寻址;如果是公有IP,就需要进行跨网段寻址。RFC 1918规定了用于组建局域网的私有IP地址。

1️⃣A类地址:10.*,前8位是网络号,共16,777,216个地址;

2️⃣B类地址:172.16.* ~ 172.31.*,前12位是网络号,共1,048,576个地址;

3️⃣C类地址:192.168.*,前16位是网络号,共65,536个地址。

⚠️包含在这个范围中的,都是私有IP,其余的则称为全局IP(或公网IP)。

我们该怎么区分每一个网段呢?

✅每一个网段都有一个接口,确定当前网段的网络号子网掩码,位于当前网段的所有设备都与这个接口连接,并且通过这个接口与外界实现通信,这个接口就是网关,路由器是最常见的网关设备

对于一个路由器,其可以配置两个IP地址,分别是WAN口IP、LAN口IP(子网IP):例如LAN为10.1.1.1/24的路由器,表示该路由器的网段网络号为10.1.1.0,设备IP范围是10.1.1.2 ~ 10.1.1.254

而每一个家用路由器,其实又作为运营商路由器的子网中的一个节点这样的运营商路由器可能会有很多级, 最外层的运营商路由器, WAN口IP就是一个公网IP了;子网内的主机想要和外网进行通信时,路由器将IP首部中的IP地址进行替换(替换成WAN IP),这样逐级替换,最终数据包中的IP地址成为一个公网IP,这种技术被称为NAT(Network Address Translation,网络地 址转换)。

📖 4. 路由选择

数据包从源设备传输到目标设备的过程,涉及到如何根据目标地址选择合适的路径进行数据转发,这就需要路由器来进行路由选择,它会根据路由表决定数据包的转发路径。

🔖原理

① 路由表

每个路由器都有一个路由表,记录了网络中所有可能的目的地和相应的转发路径。路由表包含了目标网络的地址、下一跳的地址(下一台路由器的地址)、以及路由的优先级(距离、延迟等)。

② 路由决策

当数据包到达路由器时,路由器查看数据包的目标IP地址,然后根据路由表决定下一跳路由器(或目标设备)将数据包传递到哪里。每一个路由器都会依此做出决策,直到数据包到达目标设备。

③ 下一跳

指的是数据包在通过路由器时,路由器根据路由表选定的下一个跳转点。它可以是另一个路由器或最终的目标主机。

④ 最优路径

路由选择的目标是找到一条有效、最优的路径。最优路径不仅是最短的路径,还可能考虑其他因素,如带宽、延迟、可靠性等。

例如:某主机的网络接口配置和路由表如下:

Destination:目的网络地址

Gateway:下一跳地址

Genmask:子网掩码

Flags:U标志表示此条目有效(可以禁用某些 条目),G标志表示此条目的下一跳地址是某个路由器的地址,没有G标志的条目表示目的网络地址是与本机接口直接相连的网络,不必经路由器转发

Iface:发送接口

这台主机有两个网络接口,一个网络接口连到192.168.10.0/24网络,另一个网络接口连到 192.168.56.0/24网络。如果要发送的数据包的目的地址是192.168.56.3:

1. 与第一行的子网掩码做与运算得 到192.168.56.0,与第一行的目的网络地址不符;

2. 再与第二行的子网掩码做与运算得到192.168.56.0,正是第二行的目的网络地址,因此从eth1接口发送

 如果要发送的数据包的目的地址是202.10.1.2:

1. 与路由表前几项进行对比,发现都不匹配;

2. 按缺省路由条目,从eth0接口发出去,发往192.168.10.1路由器;

3. 由192.168.10.1路由器根据它的路由表决定下一跳地址;

🔖类型

① 静态路由

静态路由是由网络管理员手动配置的路由。在网络的路由表中,静态路由条目不会自动改变,只有在手动修改时才会更新。用于小型网络或一些特定的网络环境中,可以提供简单且明确的路由路径

② 动态路由

动态路由是通过路由协议自动发现和维护路由信息的过程。路由器会定期交换路由信息,自动更新路由表,以适应网络拓扑的变化。常用于较大的、不断变化的网络环境。

📚二、ARP协议(数据链路层)

📖 1. 以太网

然而仅通过IP地址,我们还是不能够实现网络通信。原因很简单,数据包最后是交给网卡进行处理,而网卡对IP地址是没有概念的,它只认MAC地址,因为MAC地址是网卡设备在出厂时烧录进硬件的信息,所以在底层,是通过MAC地址进行数据传输的

🔖MAC地址

每个网络设备(如网卡、交换机、路由器等)在出厂时会由制造商根据全球唯一的规则分配MAC地址,且通常不可更改,换句话说,MAC地址唯一标识网络设备,由6个字节(48位)组成:

00:1A:2B:3C:4D:5E  或  00-1A-2B-3C-4D-5E

于是当网络层的IP数据包交付给数据链路层时,还需要进一步封装,添加源MAC和目的MAC地址等信息:

在局域网中,数据通过MAC地址定位目标主机来传输,这种技术就是以太网。上述格式就是以太网帧格式

 源地址和目的地址是指网卡的硬件地址(也叫MAC地址), 长度是48位,在网卡出厂时确定;

 帧协议类型字段有三种值,分别对应IP、ARP、RARP;

 帧末尾是CRC校验码。

📖 2. ARP协议

但是源主机在网络通讯时,只知道目的主机的IP地址和端口号,却不知道目的主机的硬件地址,所以在数据链路层,需要将IP地址转换成对应的MAC地址,ARP协议的作用就是建立了主机 IP地址 和 MAC地址 的映射关系。因此网络通信的过程为:

① 得知目标主机IP地址;

② 向局域网广播,申请MAC地址回复;

③ 收到MAC地址,封装数据包,进行数据传输。

其中第二步就是ARP协议需要进行工作。下面举个例子:

1. 源主机发出ARP请求,询问“IP地址是192.168.0.1的主机的硬件地址是多少”,并将这个请求广播到本地网段(以太网帧首部的硬件地址填FF:FF:FF:FF:FF:FF表示广播);

2. 目的主机接收到广播的ARP请求,发现其中的IP地址与本机相符,则发送一个ARP应答数据包给源主机,将自己的硬件地址填写在应答包中;

3. 每台主机都维护一个ARP缓存表,可以用arp -a命令查看。缓存表中的表项有过期时间(一般为20分钟),如果20分钟内没有再次使用某个表项,则该表项失效,下次还要发ARP请求来获得目的主机的硬件地址

❓为什么ARP缓存表需要过期机制

1️⃣在局域网内,设备的IP地址有可能发生变化,如果ARP缓存没有过期或更新,设备仍然会尝试使用旧的MAC地址进行通信,导致数据包无法正确送达目标设备

2️⃣网络中的ARP缓存可能被恶意篡改(例如ARP欺骗攻击),这可能导致数据包被错误地转发到攻击者设备。过期机制能够确保ARP缓存表中的信息定期被更新,这有助于防止恶意攻击

🔖格式

 下面是ARP数据报的格式:

① 硬件类型指链路层网络类型,1为以太网;

② 协议类型指要转换的地址类型,0x0800为IP地址;

③ 硬件地址长度对于以太网地址为6字节;

④ 协议地址长度对于和IP地址为4字节;

⑤ op字段为1表示ARP请求,op字段为2表示ARP应答。


以上就是【从逻辑寻址到物理传输:解构IP协议与ARP协议的跨层协作】的全部内容,欢迎指正~ 

码文不易,还请多多关注支持,这是我持续创作的最大动力!

相关文章:

【Linux-网络】从逻辑寻址到物理传输:解构IP协议与ARP协议的跨层协作

🎬 个人主页:谁在夜里看海. 📖 个人专栏:《C系列》《Linux系列》《算法系列》 ⛰️ 道阻且长,行则将至 目录 📚前言 📖 IP地址的组成 🔖IPv4 🔖IPv6 &#x1f4da…...

毕业离校管理系统的开发与需求分析

在当今信息化的时代背景下,高校的毕业生离校管理工作也逐渐向数字化转型。为了提高工作效率,减少人为错误,增强信息透明度,毕业离校管理系统应运而生。该系统旨在为学校提供一个高效、准确的毕业生离校管理平台,从而提…...

【NLP 24、实践 ⑤ 计算Bert模型中的参数数量】

以前不甘心,总想争个对错,现在不会了 人心各有所愿,没有道理可讲 —— 25.1.18 计算Bert模型结构中的参数数量 BertModel.from_pretrained():用于从预训练模型目录或 Hugging Face 模型库加载 BERT 模型的权重及配置。 参数名称…...

一、Spring框架系统化学习路径

系统化的Spring框架学习路径 第1阶段:基础知识准备 Java基础 核心概念:面向对象、异常处理、集合框架、多线程等。JVM基础:内存模型、垃圾回收机制。 Maven或Gradle Maven:创建项目、依赖管理、生命周期。Gradle:基本…...

Midscene.js - AI驱动,轻松实现UI自动化

UI自动化测试一直是软件测试中的一项重要任务,而随着AI技术的快速发展,自动化测试的能力也在不断提升。如何让UI自动化更智能、精准、灵活?Midscene.js作为一款AI驱动的UI自动化测试工具,正逐步改变着传统自动化测试的面貌。你是不…...

(九)Mapbox GL JS 中 Marker 图层的使用详解

什么是 Marker? 在 Mapbox GL JS 中,Marker(标记) 是一个可视化元素,用于在地图上标记特定的地理位置。它可以是一个默认的图标、自定义的图像,或者任何 HTML 元素。Marker 不仅能显示位置,还能…...

2k1000LA 使能 nand.

背景 : 默认的 发货的镜像 确实 是识别不了 nand 的。 ------------------------------------------------------------------------------------------ 但是 我之前 已经写好了文档,因此 拷贝到线上。 1 首先我要使能这几个。 在menuconfig 中使能一下。...

Junit+Mock

base project <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.6.11</version><relativePath/></parent><dependencies><!--添加mysql依…...

maven编译出错,javac: ��Ч��Ŀ�귢�а�: 17

1、异常信息 javac: &#xfffd;&#xfffd;Ч&#xfffd;&#xfffd;Ŀ&#xfffd;귢&#xfffd;а&#xfffd;: 17 &#xfffd;&#xfffd;: javac <options> <source files> -help &#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;г&a…...

Vue使用Three.js加载glb (gltf) 文件模型及实现简单的选中高亮、测距、测面积

安装&#xff1a; # three.jsnpm install --save three 附中文网&#xff1a; 5. gltf不同文件形式(.glb) | Three.js中文网 附官网&#xff1a; 安装 – three.js docs 完整代码&#xff08;简易demo&#xff09;&#xff1a; <template><div class"siteInspe…...

<el-table>右侧有空白列解决办法

问题如图&#xff1a; 解决办法&#xff1a;.box 为本页面最外层的class名&#xff0c;保证各个页面样式不会互相污染。 .box::v-deep .el-table th.gutter {display: none;width: 0}.box ::v-deep.el-table colgroup col[namegutter] {display: none;width: 0;}.box::v-deep …...

Linux网络 网络层

IP 协议 协议头格式 4 位版本号(version): 指定 IP 协议的版本, 对于 IPv4 来说, 就是 4. 4 位头部长度(header length): IP 头部的长度是多少个 32bit, 也就是 4 字节&#xff0c;4bit 表示最大的数字是 15, 因此 IP 头部最大长度是 60 字节. 8 位服务类型(Type Of Service):…...

系统讨论Qt的并发编程——逻辑上下文的分类

目录 前言 首先&#xff0c;讨论Qt里常见的三种上下文 同一线程的串行执行 同一线程的异步执行 多线程的执行 moveToThread办法 前言 笔者最近看了一个具备一定启发性质的Qt教程&#xff0c;在这里&#xff0c;笔者打算整理一下自己的笔记。分享在这里. 首先&#xff0c…...

《Linux Shell 脚本深度探索:原理与高效编程》

1. 基本结构 Shebang 行 #!/bin/bash # Shebang 行指定了脚本使用的解释器。 /bin/bash 表示使用 Bash 解释器执行脚本。 注释 # 这是注释&#xff0c;不会被执行 2. 变量 定义变量 variable_namevalue # 不需要加 $ 来定义变量。 # 变量名不能包含空格或特殊字符。 访…...

深入剖析:基于红黑树实现自定义 map 和 set 容器

&#x1f31f; 快来参与讨论&#x1f4ac;&#xff0c;点赞&#x1f44d;、收藏⭐、分享&#x1f4e4;&#xff0c;共创活力社区。&#x1f31f; 在 C 标准模板库&#xff08;STL&#xff09;的大家庭里&#xff0c;map和set可是超级重要的关联容器成员呢&#x1f60e;&#x…...

在大数据项目中如何设计和优化数据模型

在大数据项目中&#xff0c;设计和优化数据模型是一个涉及多个步骤和维度的复杂过程。以下是我通常采取的方法&#xff1a; 一、数据模型设计 明确业务需求&#xff1a; 深入了解项目的业务场景和目标&#xff0c;明确数据模型需要解决的具体问题。与业务团队紧密合作&#xf…...

JavaScript querySelector()、querySelectorAll() CSS选择器解析(DOM元素选择)

文章目录 基于querySelector系列方法的CSS选择器深度解析一、方法概述二、基础选择器类型1. 类型选择器2. ID选择器3. 类选择器4. 属性选择器 三、组合选择器1. 后代组合器2. 子元素组合器3. 相邻兄弟组合器4. 通用兄弟组合器 四、伪类与伪元素1. 结构伪类2. 状态伪类3. 内容伪…...

Linux系统中处理子进程的终止问题

1. 理解子进程终止的机制 在Unix/Linux系统中&#xff0c;当子进程终止时&#xff0c;会向父进程发送一个SIGCHLD信号。父进程需要捕捉这个信号&#xff0c;并通过调用wait()或waitpid()等函数来回收子进程的资源。这一过程被称为“回收僵尸进程”。 如果父进程没有及时调用w…...

Docker 不再难懂:快速掌握容器命令与架构原理

1. Docker 是容器技术的一种 容器&#xff08;Container&#xff09;概述 容器&#xff08;Container&#xff09;是一种轻量级的虚拟化技术&#xff0c;它将应用程序及其所有依赖环境打包在一个独立的、可移植的运行时环境中。容器通过操作系统级的虚拟化提供隔离&#xff0…...

取消票证会把指定的票证从数据库中删除,同时也会把票证和航班 等相关表中的关联关系一起删除。但在删除之前,它会先检查当前用户是否拥有这张票

在做航班智能客服问答系统时会遇到取消票证的场景&#xff0c;这里涉及数据库的操作时会把指定的票证从数据库中删除&#xff0c;同时也会把票证和航班等相关表中的关联关系一起删除。但在删除之前&#xff0c;需要先检查当前用户是否拥有这张票&#xff0c;只有票主才有权限取…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!

5月28日&#xff0c;中天合创屋面分布式光伏发电项目顺利并网发电&#xff0c;该项目位于内蒙古自治区鄂尔多斯市乌审旗&#xff0c;项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站&#xff0c;总装机容量为9.96MWp。 项目投运后&#xff0c;每年可节约标煤3670…...

Python爬虫(二):爬虫完整流程

爬虫完整流程详解&#xff08;7大核心步骤实战技巧&#xff09; 一、爬虫完整工作流程 以下是爬虫开发的完整流程&#xff0c;我将结合具体技术点和实战经验展开说明&#xff1a; 1. 目标分析与前期准备 网站技术分析&#xff1a; 使用浏览器开发者工具&#xff08;F12&…...

JVM虚拟机:内存结构、垃圾回收、性能优化

1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...

Java求职者面试指南:计算机基础与源码原理深度解析

Java求职者面试指南&#xff1a;计算机基础与源码原理深度解析 第一轮提问&#xff1a;基础概念问题 1. 请解释什么是进程和线程的区别&#xff1f; 面试官&#xff1a;进程是程序的一次执行过程&#xff0c;是系统进行资源分配和调度的基本单位&#xff1b;而线程是进程中的…...

【JVM】Java虚拟机(二)——垃圾回收

目录 一、如何判断对象可以回收 &#xff08;一&#xff09;引用计数法 &#xff08;二&#xff09;可达性分析算法 二、垃圾回收算法 &#xff08;一&#xff09;标记清除 &#xff08;二&#xff09;标记整理 &#xff08;三&#xff09;复制 &#xff08;四&#xff…...

android13 app的触摸问题定位分析流程

一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...

深入理解Optional:处理空指针异常

1. 使用Optional处理可能为空的集合 在Java开发中&#xff0c;集合判空是一个常见但容易出错的场景。传统方式虽然可行&#xff0c;但存在一些潜在问题&#xff1a; // 传统判空方式 if (!CollectionUtils.isEmpty(userInfoList)) {for (UserInfo userInfo : userInfoList) {…...

算法—栈系列

一&#xff1a;删除字符串中的所有相邻重复项 class Solution { public:string removeDuplicates(string s) {stack<char> st;for(int i 0; i < s.size(); i){char target s[i];if(!st.empty() && target st.top())st.pop();elsest.push(s[i]);}string ret…...

Linux-进程间的通信

1、IPC&#xff1a; Inter Process Communication&#xff08;进程间通信&#xff09;&#xff1a; 由于每个进程在操作系统中有独立的地址空间&#xff0c;它们不能像线程那样直接访问彼此的内存&#xff0c;所以必须通过某种方式进行通信。 常见的 IPC 方式包括&#…...

【51单片机】4. 模块化编程与LCD1602Debug

1. 什么是模块化编程 传统编程会将所有函数放在main.c中&#xff0c;如果使用的模块多&#xff0c;一个文件内会有很多代码&#xff0c;不利于组织和管理 模块化编程则是将各个模块的代码放在不同的.c文件里&#xff0c;在.h文件里提供外部可调用函数声明&#xff0c;其他.c文…...