吃透BGP,永远绕不开这些基础概述,看完再也不怕BGP了!

news2024/11/24 22:46:10

你们好,我的网工朋友。

总有人在私信里抱怨,BGP实在是太难了!

一是这玩意儿本来就很复杂,需要处理大量的路由信息和复杂的算法;再一个是需要你有一定的实战经验才能深入理解运作。

虽然BGP确实有一定难度,但你总得先从技术理论开始吃透它吧?

学习掌握了BGP,对工作中提高网络性能、增强网络稳定性以及安全性等等多方面,都挺关键的。

想吃透BGP,绕不开我今天要说的这些基础概述和实例!

今日文章阅读福利:《BGP选路规则专题文档(华为官方出品)-78页》

私信我,备注“BGP”,即可获取这份专题文档。

01 基础概述

说BGP之前,我们先从计算机网络的基础开始说起。

当前所使用的计算机网络中,一个网络通常用一个IP网段来表示。

要将所有网络连接起来,并且要通信,就需要将这些IP网段连接起来,让每个IP网段都知道其它IP网段的信息,就可以实现全网通信。

将网络与网络连接起来的设备都是路由器,只要网络中每一台路由器都得知所有的IP网段信息,就可以为全网提供数据转发。

如果某一台路由器不能得知所有的IP网段信息,也就表示这台路由器所连接的网络不能与其他网段通信。

为了帮助路由器获得全网IP网段信息,因此路由协议工作在路由器与路由器之间,让网络中每一台路由器都拥有全网完整的路由信息,从而实现全网可达。

从上可以看出,路由协议在路由器之间传递路由信息,是保证网络通信的基础。

如果路由器协议传递了错误的路由信息,或者没有传递路由信息,将导致某些网络通信的中断,所以路由协议从一台路由收到路由更新后,必须毫不保留地传递给其它路由器。

而当一个网络失效后,也必须告知其它路由器该网段不可达,需要将相应路由器删除。

当全网每一台路由器都需要拥有所有的路由信息,并且完全一致时,这种状态被称为收敛状态,一个网络只有在收敛状态时,才能保证全网可达。

而当今所使用的庞大的互联网,是由数万台路由器连接起来的。

如果每一台路由器都拥有互联网中的每一条路由信息,那么就意味着每一台路由器都将拥有数十万甚至数百万条路由条目,这个数量是惊人的。

但是由于路由协议的特征以及互联网全网通信的需求,就必须让互联网中每一台路由器将自己的路由信息与其它路由器互换,使整个互联网的达到收敛状态。

虽然这是铁定的要求,但是请仔细想一下,这是万万不可能的。

因为一个拥有数万台路由器组建起来的超大型网络,永远不可能达到收敛状态。

当某个网络断开时,先得知的路由器需要将这个信息告知给其它所有路由器,因为信息是一台传一台传过去的,所以一个网络断开的信息要让数万台路由器都知道,这需要很长的时间。

并且可能在这个信息还没有传遍整个网络时,这个之前中断的网络就恢复了正常。

那么这时,先知道的路由器又要重新向网络中通告该网段恢复正常的信息。

如此一来,互联网中不断变化的网络,会让所有路由器不停地传递路由信息,结果是导致网络中路由信息的不一致,也将导致庞大的路由更新影响所有路由器的性能。

因此,互联网中,一个网络的中断与恢复,实在没有必须通告给数以万计的路由器。

而网络的信息,必须向其它路由器通告。

那么,一台路由器的路由信息,既然没有必须向网络中每一台路由器通告,它究竟该通告给哪些路由器呢?

或者换句话说,它的路由更新通告的范围究竟有多大呢?

基于以上种种原因,所以我们将–台路由器的路由更新限制在一定的范围内,也只有这样,一个被划分为更小范围的网络,才能达到收敛状态。

所以现实情况是,我们的互联网被划分成了一个一个更小范围的网络。

任何一台路由器的路由更新,被限制在这个特定的范围内,而这个特定的范围,就是你应该知道的被称为自治系统的网络范围,即autonomous system (AS)。

互联网中路由协议的更新只应该在一一个AS内部传递。

但是互联网是需要全网通信的,所以必须让每一个AS都能够获得其它AS的路由信息才行。

因此,路由协议被定义为两种截然不同的种类,即只在一一个AS内部更新的路由协议,称为Interior Gateway Protocol(IGP) 。

以及在AS 与AS之间更新的路由协议,称为 Border Gateway Protocol (BGP) 。

需要更多的解释,将互联网划分成多个AS,目的并不仅仅是将路由协议的更新限制在特定的范围内;

还有一个重要的原因是,将互联网划分成若千个小范围的网络后,那么这每一个小网络就可以单独定义各自的路由策略与安全策略,并且这样不需要干扰其它AS,也不受其它AS干扰。

比如网络中若干的ISP,这些ISP对自己的网络需要制定自己的策略,又需要让这些策略保持私有性而不与其它ISP互相干扰,所以划分AS,帮他们实现了这个目的。

只能在一个AS内部传递更新的IGP路由协议有RIP, EIGRP, OSPF, IS-IS, 可以在AS之间传递更新的路由协议目前只有BGP。

但是有个特别之处是,EIGRP 也使用了AS的概念来工作。

运行EIGRP的网络也会被划分成多个AS,虽然默认情况下,EIGRP不能在AS与AS之间更新路由信息,但是EIGRP也可以实现AS之间的路由更新。

需要说明的是,EIGRP概念中的AS与BGP的AS并无任何关联,它们之间没有任何共同操作性。

真正的AS是指BGP的AS,而EIGRP不管有什么样的AS特征,它永远被限制在BGP的单一AS之中。

02 BGP AS

对于BGP的AS号码的分配,是由Internet Assigned Number Authority(IANA)机构来统一规划和分配的。

IOS中运行的BGP,目前最多支持4字节长度的AS号码,但并不表示所有AS号码都能任意配置。

在2009年1月之后,(IANA)决定使用4字节长度AS范围是65535-4294967295。

当前,通常还是使用2字节长度的AS,也就是1-65535,所以不对4字节的AS号码做太多讨论。

因为BGP是使用在互联网之中的,互联网由多个BGP AS域组成,所以互联网中不能出现AS号码相同的域。

如果一台路由器要接入互联网并运行BGP,那么必须向IANA申请合法的AS号码。

为了考虑到某些大型企业需要使用BGP与ISP对接,而又没有足够的AS号码用来给企业用户,所以将AS号码划分为公有AS和私有AS。

公有AS的范围是1-64511,私有AS范围是64512-65534。

公有AS只能用于互联网,并且全球唯一,不可重复,而私有AS可以在得不到合法AS的企业网络使用,可以重复。

很显然,因为私有AS可以被多个企业网络重复使用,所以这些私有AS不允许传入互联网,ISP在企业用户边缘,需要过滤掉带有私有AS号码的路由条目。

03 BGP 邻居

如果你在自己的PC上从某个FTP服务器下载文件,那么你的PC只要和FTP服务器是通畅的即可。

也就是说你的PC只要ping得通FTP服务器就行,不管距离有多远,因为不可能从FTP服务器上下载文件的PC都与之是直接连在一起的。

PC从FTP服务器下载文件时,使用的是TCP传输,当数据在中途出现丢包时,被丢弃的数据包能够得到重新传递,从而保证下载的文件是完整的。

由于BGP运行在整个互联网,传递着数量庞大的路由信息,因此需要让BGP路由器之间的路由传递具有高可靠性和高准确性;

所以BGP路由器之间的数据传输使用了TCP协议,端口号为179,并且指的是会话目标端口号为179,而会话的目标端口号为179,而会话源端口号是随机的。

正因为BGP使用了TCP协议传递,所以两台运行BGP的路由器只要通信正常,也就是说只要ping得通,而不管路由器之间的距离有多远,都能形成BGP邻居,从而互换路由信息。

一个配置BGP进程的路由器只能称为BGP-Speaker,当和其它运行了BGP的路由器形成邻居之后,就被称为BGP-Peer。

如果一个网络中的多台路由器都运行OSPF之后,那么这些路由器会在相应网段去主动发现OSPF邻居,并主动和对对方形成OSPF邻居。

而一个路由器运行BGP后并不会主动去发现和寻找其它BGP邻居,BGP的邻居必须手工指定。

BGP和其它路由协议一样,传递的是网络层协议,如IP协议,除此之外,BGP还能够传递除IP协议之外的其它网络层协议,能够传递的协议如下:

!! IP Version 4 (IPv4) IP Version 6 (IPv6)
Virtual Private Netwoks version 4 (VPNv4)
Connectiononless Network Service (CLNS)
Layer 2 VPN(L2VPN)

这些协议都被为 address family,配置时,需要进入相应的协议 address family 模式,而IPv4除外。

所有命令在address family 中独立配置,独立生效,并且都拥有独立的数据库。

正常的BGP配置模式被称为NLRI模式中配置,在NLRI模式中配置的参数只对IPv4单播生效。

IOS支持四个AFI模式,为IPv4,IPv6,CLNS,VPNv4,并且IPv4和IPv6还有单播和组播之分。

思科路由器运行的BGP为version4,一台路由器只能运行一个BGP进程,并且整台路由器只能属于一个AS;

但是一台路由器可以承载多个address Family,而一个支持多个address family 的BGP和一个不支持的可以正常通信,但这也仅限于IPv4。

一台BGP路由器运行在一个单一的AS内,在和其它BGP路由器建立邻居时,如果对方路由器和自己属于相同AS,则邻居关系为 Internal BGP(iBGP),如果属于不同AS,则邻居关系为external BGP (eBGP)。

BGP要求eBGP邻居必须直连,而iBGP邻居可以任意距离,但这些都是可以改变的。

在BGP形成邻居后,开始会交换所有路由信息,但是之后都采用增量更新,也就是只有在路由有变化时才更新,并且只更新有变化的路由。

BGP建立邻居后,开始后,会通过相互发送类似hello包的数据来维持邻居关系,这个数据包称为Keepalive,便认为邻居丢失,则断开与邻居的连接。

BGP之间建立邻居,需要经历如下几个过程:

  • Idle——BGP 进程被启动或被重置,这个状态是等待开始,比如等于指定一个BGPpeer,当收到TCP连接请求后,便初始化另外一个事件,当路由器或peer重置,都会回到idle状态。
  • Connect——检测到有peer要尝试建立TCP连接。
  • Active——尝试和对方peer建立TCP连接,如有故障,则回到idle状态。
  • OpenSent——TCP 连接已经建立,BGP发送了一个0PEN消息给对方peer,然后切换到OpenSent状态,如果失败,则切换到Active状态。
  • OpenReceive——收到对方peer的OPEN消息,并等待keepalive消息,如果收到keepalive,则转到Establ ished状态,如果收到notification,则回到idle状态,比如错误或配置改变,都会发送notification而回到idle状态。
  • Established——从对端peer收到子keepalive,并开始交换数据,收到keepalive后,holdtimer都会被重置,如果收到notification,就回到idle 状态。

05 BGP 更新源

BGP并不能主动在网络中寻找邻居,必须手工指定BGP邻居的地址,那么BGP才会将数据包发往指定的地址来请求建立邻居。

与此同时,BGP发出的请求数据包除了写明目标IP地址外,还要写上自己的IP地址,即BGP源地址。

路由器自己产生流量后从接口发出时,流量从哪个接口被发出,那么这些数据包的源IP地址就是哪个接口的地址。

因此当BGP发出数据包寻找邻居时,这些数据包从那些接口被发出,那么BGP源IP地址就是哪个接口的地址。

要两台BGP路由器要正常建立邻居,必须双方路由器都相互指定邻居,相互发送数据包才行。

当一台BGP路由器收到建立邻居的请求后,如果发现数据包的目标IP不是自己的BGP源地址。

那么就拒绝该连接的请求后,只有当请求数据包的目标与自己的BGP源地址相同时,才可建立BGP邻居。

需要注意的是,这个条件只在两个邻居之间,任意一个邻居满足条件即可,并不需要双方都满足;

也就是说一方收到的数据包目标IP与自己的BGP源地址相同即可;

另一方收到的数据包目标IP与它的BGP源地址不同也没关系,只要单方面符合条件就行,但我们通常都将BGP两端的源与目标保持一致。

BGP 的源地址是可以随意更改的,但只能是路由器上的接口地址。如下图:

在上图中,R1与R2之间有两条链路。

当配置BGP邻居时,如果R1指定邻居地址为12. 1.1.2, R2指定邻居地址为12. 1.1.1。

那么在建立邻居过程中,R1 将请求数据包从接口F0/0发出,数据包的目标IP为12. 1. 1.2, BGP 源地址为F0/0的接口地址12. 1.1.1。

当R2将请求数据包从接口F0/0发出时,数据包的目标IP为12.1. 1.1, BGP 源地址为F0/0的接口地址12. 1.1.2。

由于R1发出的数据包目标IP12. 1.1.2与R2的BGP源地址12. 1. 1.2完全相同,所以最终能够正常建立BGP邻居。

R1在检测地址时,R2的目标IP与R1的源也完全相同,通常我们都保证双方一致。

当R1与R2之间的直连接口F0/0中断后,如果双方将数据包从S0/0发出,那么R1的源地址就是10. 1. 1.1, R2的源地址就是20. 1.1.2;

由此可以看出,双方发出的数据包的目标IP都与对方的源地址不符,所以无法建立BGP邻居。

虽然在上面的网络环境中,双方路由器之间都拥有多条链路,在中断某条链路之间,仍然可以通信,但是这并不能保证BGP邻居的永久连接。

为了使拥有多条链路的BGP邻居之间永远保持连接,考虑到路由器的loopback口在设备正常工作的情况下,不会像物理接口那样出现中断,所以建议在BGP邻居之间使用loopback 接口的地址来建立TCP连接。

当指定邻居时,不再将邻居的地址指定为对方物理接口地址,而改为指定对方的loopback地址。

这样一来,既然物理接口中断,只要还有通畅的链路,那么BGP邻居仍然可以保持连接。

在将BGP邻居地址指定为对方loopback地址时,为了使数据包的目标IP与对方的BGP源地址相同,所以邻居也要将BGP源地址更改为自己的loopback接口地址,从而使得双方正常建立BGP连接。

在上图中,当R1指定邻居地址为2.2.2.2,BGP 源地址为1.1.1.1, 而R2指定邻居地址为1.1.1.1, BGP源地址为2.2.2.2,这样一来,双方的目标IP都与对方的BGP源地址相同。

所以可以正常建立邻居,并且在双方链路中,任何一条链路断开,都不影响邻居的会话,BGP 的连接仍然保持而不会中断,实现了连接的冗余性和稳定性。

06 BGP TTL

BGP的路由可能会从一个AS发往另外一个AS,从而穿越多个AS。

但是由于运行BGP的网络会是一个很大的网络,路由从一个AS被发出,可能在经过转发之后,又回到了开始的AS之中,形成路由环路。

所以出于防止环路的目的考虑,BGP 在将路由发往其它AS时,也就是发给eBGP邻居时,需要在路由中写上自己的AS号码。

下一个 AS收到路由后,再发给其它AS时,除了保留之前的AS号码之外,也要添加上自己的AS号码。

这样写在路由中的AS被称为AS -path,如果BGP收到的路由的AS_ PATH中包含自己的AS号码,就认为路由被发了回来,以此断定出现了路由环路,就会丢弃收到的路由。

BGP只有在将路由发给eBGP时,才会在AS- path中添加自己的AS号码,而在发给iBGP时,是不会添加AS号码的。

因为iBGP邻居在同一个AS中,即使要添加,AS 号码全是一样的,所以没有必要。

在上图中,当路由穿越各个AS时,所有发给eBGP邻居的路由,都会在AS-path中添加自己的AS,自己的AS总是添加在AS-path的前面。

例如:

一条路由从AS10被发往AS 20,则AS-path为“10”,当AS 20 将路由发往AS 30时,添加上自己的AS号码20之后,AS- path变成“20, 10”,当AS 30将路由发往AS 50时,AS 50收到的路由的AS-path为“30, 20, 10”。

当AS 30将路由发给AS 40, AS 40再将路由发给AS 10时,路由的AS- path为“40, 30,20, 10”;

由于AS 10 在收到路由后,发现AS- path中包含自己的AS号码10,所以认为出现环路,便丢弃收到的所有路由。

在IGP协议中,我们将路由协议分成两大类:距离矢量路由协议和链路状态路由协议,而BGP被划分为路径矢量路由协议(path-vector routing) ,路径矢量算法结合了距离矢量特性与AS- path防环特性。

因为BGP在将路由发给eBGP邻居时,会将自己的AS号码添加到AS- path中,所以可以以此来防止环路。

而在将路由发给iBGP时,是不会往AS -path添加AS号码的,因此在iBGP之间传递路由时,没有防止环路的机制。

考虑到为iBGP之间的路由传递也加入防环机制,因而强制将BGP路由在AS内部只传一跳。

具体操作为

一台BGP路由器从eBGP邻居收到路由,发给iBGP邻居之后,iBGP邻居收到后就不能再传给其它任何iBGP邻居,只能传递给eBGP邻居。

此规则被多数人称为BGP的水平分割,就是一台BGP路由器从iBGP邻居收到的路由,不能传递给其它iBGP 邻居,只能传给eBGP邻居。如下图:

在上图中,当R1从eBGP邻居R6那里收到路由后,可以发给任何iBGP邻居,包括R3和R4。

当R3从iBGP邻居R1那里收到路由后,不可以转发给任何iBGP邻居,只可以转发给eBGP邻居,所以R3从R1收到路由后,只能转发给eBGP邻居R5。

由于R3和R4从R1收到路由后,都不可以转发给iBGP邻居R2。

在上图环境中,终造成R2无法接收任何路由,要让R2收到路由,建议在R1与R2之间再建立一条BGP会话。

所以如此一来,在同一个AS中,要将路由全网传递,就需要在iBGP邻居之间配置全互联,最终AS 20内的邻居关系如下图:

在AS内部,除了建立全互联的iBGP邻居关系外,还可以通过BGP Reflector (BGP反射器)和BGP Confederation(BGP联邦)的方式来实现路由全网传递,将在后续介绍。

07 BGP路由表

当路由器之间建立BGP邻居之后,就可以相互交换BGP路由。

一台运行了BGP协议的路由器,会将BGP得到的路由与普通路由分开存放,所以BGP路由器会同时拥有两张路由器:

一张是存放普通路由的路由表,被称为IGP路由表。

就是平时我们使用命令show ip route 看到的路由表,IGP 路由表的路由信息只能从IGP协议和手工配置获得,并且只能传递给IGP协议。

另外一张就是运行BGP之后创建的路由表,称为BGP路由表。

需要通过命令show ip bgp才能查看,BGP路由表的路由信息只能传递给BGP协议,如果两台BGP邻居的BGP路由表为空,就不会有任何路由传递。

在初始状态下,BGP 的路由表为空,没有任何路由,要让BGP传递相应的 路由,只能先将该路由导入BGP路由表,之后才能在BGP邻居之间传递。

默认情况下,任何路由都不会自动进入BGP路由表,BGP路由表的路由获得有多种方式:

可以从BGP邻居获得,也可以手工将IGP路由导入BGP路由表,还可以将其它路由重分布进BGP。

只要BGP的路由不是从邻居学习到的而是手工导入的,那么这样的路由被称为BGP本地路由。

因为BGP的邻居类型分为两种:

eBGP和iBGP,所以BGP路由的AD值也有区分,如果BGP的路由是从eBGP学习到的,AD值为20。

可以发现,从eBGP邻居学习到的路由,将优于任何IGP协议:从iBGP学习到的路由的AD值为200,同样可以发现,此类路由的优先级低于任何IGP协议。

BGP 除了以上两种AD值之外,如果BGP 路由是从本地手工导入的,即BGP本地路由,则BGP本地路由的AD值为200,与iBGP路由的AD值相同,优先级低于任何IGP协议。

如果某一条相同的路由同时从eBGP和iBGP以及本地路由学习到,那么究竟哪条路由会被选择为最优路径呢?

路由的AD值并不一定会影响到路径选择,因为BGP并不会在一开始,就通过比较AD值来选择最优路径。

08 BGP 同步

BGP邻居之间的通信与交流运行在TCP的基础上,在两个节点之间,只要网络是通的,就能够建立TCP。

网络的连通,可以是任何IGP路由协议,甚至是静态路由,总之,只要网络是通的,TCP 连接就一定能够建立起来。

只要让两台路由器之间连通,保证TCP能够正常连接,就能够保证BCP的通信。

在一个AS中,除了需要建立BGP连接之外,同时还需要运行FGP协议。

其中运行BGP的目的是为了在大型网络中传递庞大的路由表或路由信息,而运行IGP协议的目的可想而知,并不是为了传递庞大的路由信息;

在AS中运行IGP的根本目的是为了让BGP路由器之间能够建立TCP连接,从而为BGP的通信服务。

因此可以看出,BGP 就像是 一辆运货的卡车,BGP 的路由就是卡车要运的货,而IGP协议就是为了在站与站之间铺平道路,如果没有IGP去让道路连通,那么BGP就无法在站与站之间运送货物。

因为BGP在建立邻居时,BGP的源地址可以是任意地址,这些地址可以不是直连的,只要是能通信的,能建立TCP连接即可。

当BGP在向邻居发送流量时,只要将流量发往邻居的对端地址,因为邻居的地址并不一定是直连的,所以要找到去往邻居地址的路径,可能需要查询IGP路由表,因为IGP为BGP的通信与连接提供了保证。

由此可见,BGP 要将数据发给邻居,BGP 在查询去往邻居的路径时,采用的是递归查询,BGP 查询去往邻居的过程中,可能要多次查询IGP路由表;

只要在IGP路由表中找到了去往邻居地址的相应路径或相应下一跳,那么就会将数据发给这个下一跳。

在上图的网络中,R1与R4建立eBGP连接,R3与R5建立eBGP连接,而R1与R3建立iBGP连接。

在R1与R3建立iBGP连接时,R1通过目标地址3.3.3.3找到邻居R3, R1的BGP源地址为1.1.1.1, 而R3也通过目标地址1. 1. 1.1找到邻居R1,R3的BGP源地址为3.3.3.3;

为了让1.1. 1.1和3.3. 3.3能够正常通信,从而建立TCP连接,R1、R2、R3之间启用了IGP协议0SPF, OSPF的目的只是为了使1.1.1.1能够与3.3.3.3通信,并不传递AS中庞大的路由信息。

当AS 10中的R4将网段10. 1.1.0/24通告给AS 20中的R1后,因为R1与R3之间是iBGP邻居,所以R1将路由10.1.1.0/24传递给R3,最终R3将路由10.1.1.0/24传递给AS30中的R5。

当R5将目的地为10.1.1.0/24的流量发给R3时,R3在查询路由表后得知,去往10.1. 1. 0/24的数据包需要发给iBGP邻居1.1.1.1才能够到达;

于是R3便执行递归查询,查询如何去往1.1.1.1,正因为R1与R3之间的通信是靠OSPF提供的,所以R3得知去往1.1.1.1必须将数据包交给R2;

即给下一跳23.1.1.2,因为R2只运行了OSPF为BGP服务,所以R2没有BGP的路由10. 1.1.0/24,当R2发现数据包的目标地址为10. 1. 1. 0/24后,只能将数据包全部丢弃,这就类似于路由黑洞。

从以上情况中可以看出,当BGP从iBGP收到路由时,因为邻居之间可能跨越了多台IGP路由器。

所以BGP在将数据包发往目的地时,通常会发给一台只运行了 IGP的路由器,而只运行IGP的路由器并没有BGP的路由,因而最终导致数据包丢失,造成路由黑洞。

要杜绝此类问题的发生,其实答案很明了,就是让AS中只运行IGP的路由器同时也拥有BGP的路由表即可。

由于以上原因,在BGP路由传递中,有以下一条规则:当BGP要将从iBGP邻居学习到的路由信息传递给其它邻居之前(这个邻居通常是eBGP邻居),这些路由必须在IGP路由表中也能学到,否则认为此路由无效而不能发给其它邻居。

此规则称为iBGP与IGP路由同步。

在上图环境中,在R3将从iBGP邻居R1学习到的路由传递给eBGP邻居R5之前,必须确定这条路由在自己的IGP路由表中也存在,否则不使用该路由。

要查看路由在IGP路由表中是否存在,使用命令show ip route 即可。

注意,只有从iBGP邻居学习到的路由,才受iBGP与IGP路由同步规则的限制,如果路由是从eBGP邻居学习到的,则不受此规则限制,并且此规则可以手工开启或关闭。

BGP同步默认是开启的,在IOS 12.2(8)T 以及之后的版本默认都是关闭的。

整理:老杨丨10年资深网络工程师,更多网工提升干货,请关注公众号:网络工程师俱乐部

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1178274.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

简简单单入门Makefile

笔记来源&#xff1a;于仕琪教授&#xff1a;Makefile 20分钟入门&#xff0c;简简单单&#xff0c;展示如何使用Makefile管理和编译C代码 操作环境 MacosVscode 前提准备 新建文件夹 mkdir learn_makefile新建三个cpp文件和一个头文件 // mian.cpp #include <iostrea…

fio数据整理之二

fio数据简单抓取 上文我们完成了一些fio output数据的简单抓取&#xff0c;本文将针对抓取的数据做进一步的处理&#xff0c;输出到表格之中&#xff0c;方便我们查看&#xff0c;统计结果。 本文先使用最简单的方法创建csv档案 我们现有个基本认知&#xff0c;在csv档案中&am…

通过you-get命令行工具下载B站等常见网站高清视频

参考&#xff1a; you-get&#xff1a;https://github.com/soimort/you-get EditThisCookie 源码&#xff1a;https://github.com/ETCExtensions/Edit-This-Cookie EditThisCookie 官网&#xff1a;https://www.editthiscookie.com/ you-get 是一个非常好用的命令行版视频下载工…

[wp]NewStarCTF 2023 WEEK5|WEB

前言:比赛是结束了&#xff0c;但我的学习还未结束&#xff0c;看看自己能复习几道题吧&#xff0c;第四周实在太难 Final 考点&#xff1a; ThinkPHP 5.0.23 RCE一句话木马上传SUID提权&#xff08;find&#xff09; 解题: 首先页面就给了ThinkPHP V5&#xff0c; 那无非考…

java制作游戏,如何使用libgdx,入门级别教学

第一步&#xff0c;进入libgdx的官网。点击get started 进入这个页面&#xff0c;点击setup a project 进入这个页面直接点击&#xff0c;Generate a project. 点击下载&#xff0c;下载创建工具 它会让你下载一个jar包&#xff0c;有java环境的人可以双击直接打开。 把android…

Linux学习之vim跳转到特定行数

参考的博客&#xff1a;《Vim跳到最后一行的方法》 《oeasy教您玩转vim - 14 - # 行头行尾》 《Linux&#xff1a;vim 中跳到首行和最后一行》 想要跳到特定行的话&#xff0c;可以在命令模式和正常模式进行跳转。要是对于vim的四种模式不太熟的话&#xff0c;可以到博客《Linu…

Arrays.asList() 和 List.of() 的列表之争

1. 概述 有时在Java中&#xff0c;为了方便&#xff0c;我们需要创建一个小列表或将数组转换为列表。Java 为此提供了一些辅助方法。 在本文中&#xff0c;我们将比较初始化小型临时数组的两种主要方法&#xff1a;List.of()和 Array.asList()。 2. Arrays.asList() Java 自…

跨境电商商城源码,助力商家全球布局(多语言切换\多货币转换\多商户入驻)

今天&#xff0c;我们要给大家介绍一款强大且多元化的跨境电商解决方案——WoShop跨境电商源码!这款源码拥有许多令人惊叹的功能&#xff0c;其中最引人注目的就是支持多语言切换、多货币转换以及多商户入驻! 设想一下&#xff0c;你是一个跨境电商的卖家&#xff0c;你的业务遍…

Cannot read properties of undefined (reading ‘prototype‘)

用vue注册的用import ElementUI from "element-ui"是不行的要用 import ElementUI from “element-plus”

【JAVA学习笔记】63 -坦克大战1.3-敌方发射子弹,击中坦克消失并爆炸,敌人坦克随机移动,规定范围限制移动

项目代码 https://github.com/yinhai1114/Java_Learning_Code/tree/main/IDEA_Chapter18/src/com/yinhai/tankgame1_3 〇、要求 增加功能 1.让敌人的坦克也能够发射子弹(可以有多颗子弹) 2.当我方坦克击中敌人坦克时&#xff0c;敌人的坦克就消失,如果能做出爆炸效果更好. …

Thread类的基本操作(JAVA多线程)

线程是操作系统中的概念&#xff0c;操作系统内核实现了线程这样的机制&#xff0c;并提供了一些API供外部使用。 JAVA中 Thread类 将系统提供的API又近一步进行了抽象和封装&#xff0c;所以如果想要使用多线程就离不开 Thread 这个类。 线程的创建(Thread类) 在JAVA中 创建…

SPSS多元方差分析

前言&#xff1a; 本专栏参考教材为《SPSS22.0从入门到精通》&#xff0c;由于软件版本原因&#xff0c;部分内容有所改变&#xff0c;为适应软件版本的变化&#xff0c;特此创作此专栏便于大家学习。本专栏使用软件为&#xff1a;SPSS25.0 本专栏所有的数据文件请点击此链接下…

大容量中间继电器 RXMH2 RK223 067 DC110V JOSEF约瑟

系列型号 RXMH2 RK 223 067大容量中间继电器&#xff1b; RXMH2 RK 223 068大容量中间继电器&#xff1b; RXMH2 RK 223 069大容量中间继电器&#xff1b; RXMH2 RK 223 070大容量中间继电器&#xff1b; 一、用途 RXMH2系列大容量中间继电器用于工业自动化控制及电力系统…

Git介绍及使用

目录 一、Git 的基本概念 1. 仓库&#xff08;Repository&#xff09;: 仓库是存储代码的地方。可以通过 命令将本地文件夹初始化为 Git 仓库&#xff0c;并使用 命令从远程仓库克隆到本地 2. 分支&#xff08;Branch&#xff09;: 分支是指从主分支上创建出来的一个分支&…

Python画一个爱心

Python画一个爱心 一、效果图二、Python代码 一、效果图 二、Python代码 import random from math import sin, cos, pi, log from tkinter import *CANVAS_WIDTH 640 # 画布的宽 CANVAS_HEIGHT 480 # 画布的高 CANVAS_CENTER_X CANVAS_WIDTH / 2 # 画布中心的X轴坐标 CA…

DCU集群搭建虚拟环境方法简介

1.conda安装方法&#xff1a; wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh #下载miniconda安装包chmod 750 Miniconda3-latest-Linux-x86_64.sh #添加执行权限bash ./Miniconda3-latest-Linux-x86_64.sh #安装下载的minnconda32.集群安装…

FreeRTOS源码阅读笔记1--task.c

在FreeRTOS中&#xff0c;创建任务有两种方式&#xff1a;动态创建和静态创建。区别就是&#xff1a;动态创建任务的栈和任务TCB是由操作系统动态分配&#xff08;malloc&#xff09;内存空间&#xff0c;任务删除时可以释放内存&#xff08;free&#xff09;&#xff1b;而静态…

单链表(无头单项非循环)

文章目录 前言概述链表的实现初始化遍历单链表创建新节点尾插头插尾删头删单链表的查找在pos位置之前插入一个节点在pos位置删除节点在pos位置后插入节点删除pos后一个节点销毁 结尾 前言 链表是一种物理存储结构上非连续、非顺序的存储结构&#xff0c;数据元素的逻辑顺序是通…

HDFS系统操作命令大全

一&#xff0c;前言 HDFS作为分布式存储的文件系统&#xff0c;有其对数据的路径表达方式 HDFS同linux系统一样&#xff0c;均是以/作为根目录的组织形式 linux&#xff1a;/usr/local/hello.txt HDFS&#xff1a;/usr/local/hello.txt 二&#xff0c;如何区分呢&#xff1f; L…

【数据结构】树与二叉树(三):二叉树的定义、特点、性质及相关证明

文章目录 5.1 树的基本概念5.1.1 树的定义5.1.2 森林的定义5.1.3 树的术语5.1.4 树的表示 5.2 二叉树5.2.1 二叉树1. 定义2. 特点3. 性质引理5.1&#xff1a;二叉树中层数为i的结点至多有 2 i 2^i 2i个&#xff0c;其中 i ≥ 0 i \geq 0 i≥0。引理5.2&#xff1a;高度为k的二叉…