浅谈网络 | 应用层之云网络隔离GRE/VXLAN

目录

    • 前言
    • GRE 隧道技术
    • VXLAN
    • GRE/VXLAN接入云平台

前言

之前提到,为云平台中的租户实现隔离时,常用的策略是基于 VLAN。然而,VLAN 只有 12 位,共支持 4096 个 ID,这在最初设计时看似足够,但随着云计算的快速发展,这一限制已无法满足需求。那么该如何应对呢?

为什么不能直接修改 VLAN 协议?
一种可能的想法是直接修改现有的 VLAN 协议,让其支持更多的 ID。然而,这种方法在实践中几乎不可行,因为:

  • VLAN 协议已经成为行业标准,广泛应用于各种网络设备和程序中。
  • 如果修改协议,就需要更新所有相关的设备和软件,这是一个巨大的工程,几乎无法完成。
    因此,直接修改协议并不现实。

扩展的思路:新增包头
另一种更为实际的方式是扩展协议,在现有的数据包格式上新增一个扩展包头,包含足够区分租户的 ID。外层包的格式仍保持与传统网络兼容,而需要区分用户时,由特定的软件或硬件处理这些带有扩展包头的特殊数据包。

这种方法与我们在第 22 讲中提到的“隧道理论”非常相似。还记得自驾游时通过摆渡轮到海南岛的例子吗?当时,隧道理论中的扩展包头主要用于加密,而这里的扩展包头则用于区分租户

Underlay 与 Overlay 网络
为了解决云平台中的隔离问题,同时兼容传统网络,我们引入了 UnderlayOverlay 网络的概念:

  • Underlay 网络:底层的物理网络,由真实的物理交换机、路由器等设备组成,承载所有基础的网络通信。
  • Overlay 网络:虚拟化的网络,由一系列基于 Underlay 网络的技术实现,用于为虚拟机和租户提供隔离、互通以及灵活的网络配置。

Overlay 网络通过在物理网络之上创建虚拟化的二层或三层网络,为每个租户提供独立的逻辑网络。扩展包头的设计正是 Overlay 网络的关键所在。

典型的 Overlay 网络技术
本章将重点讲解两种常用的 Overlay 网络技术,分别是 VXLAN(虚拟扩展局域网)GRE 隧道技术。它们通过新增包头的方式,突破了 VLAN 的局限,同时保持了对传统网络的兼容性。

这种扩展和隧道化的方式,不仅解决了隔离问题,还使得云平台的网络更灵活、更适应大规模、多租户的需求。

GRE 隧道技术

第一个 Overlay 网络技术是 GRE(Generic Routing Encapsulation),即通用路由封装。它是一种 IP-over-IP 的隧道技术,可以将 IP 数据包封装在 GRE 包中,外面再加上一层 IP 头。隧道的一端负责封装数据包,在传输过程中通过隧道传递,另一端则负责解封装。可以将 GRE 隧道理解为一种虚拟的点对点连接。
在这里插入图片描述

GRE 包头结构

在 GRE 包头中:

  1. 前 32 位 是固定存在的,主要用于隧道的基础功能。
  2. 后续字段 是可选的,是否包含这些字段由包头中的标志位决定。
  3. Key 字段 是一个非常重要的部分,它是一个 32 位字段,常用于区分不同的用户或隧道连接。在云平台中,这个字段存储的是 Tunnel ID,而 32 位的大小已经足以满足大规模云平台的需求。

在专用于网络虚拟化的 GRE 包头格式中,有一种叫做 NVGRE(Network Virtualization GRE) 的扩展版本,它提供了一个 24 位的网络 ID 字段。这个网络 ID 号足够表示 16,777,216 个虚拟网络,完全能够满足云平台的需求。

GRE 隧道的实现
GRE 隧道的封装和解封装需要由支持路由功能的设备来完成,这些设备可以是专用路由器,也可以是启用了路由功能的 Linux 服务器。GRE 隧道建立后,会在路由设备上生成虚拟的 Tunnel 端口,专门用于封包和解封包操作。

GRE 隧道的通信过程

GRE 隧道的传输过程如下:

  1. 在两个网络设备之间建立隧道,隧道的起点和终点由设备上的 Tunnel 端口表示。
  2. 数据包从源网段发出后,通过隧道的入口端口进行封包,添加 GRE 包头和外层 IP 头。
  3. 数据包在物理网络中传输,GRE 包头中的 Key 字段 用于标识数据包所属的隧道。
  4. 数据包到达隧道出口后,解封 GRE 包头和外层 IP 头,并将原始 IP 包转发到目标网段。
    在这里插入图片描述

主机 A 想要访问主机 B,发送一个网络包:

  • 源 IP 地址:192.168.1.102
  • 目标 IP 地址:192.168.2.115

由于主机 B 在不同的网段,主机 A 会根据默认路由规则将数据包发送给默认网关(左侧路由器的地址 192.168.1.1)。

  1. 左侧路由器封装数据包
    左侧路由器接收到主机 A 发来的数据包后,根据路由表发现目标网段(192.168.2.0/24)需要通过 GRE 隧道来访问。此时,路由器执行以下操作:

    • 封装数据包
      • 在原始 IP 头(源地址 192.168.1.102,目标地址 192.168.2.115)之外,加上一个 GRE 头
      • 对于 NVGRE,这一步会在 MAC 头之后添加 GRE 头,并包括一个租户隔离的网络 ID。
    • 添加外部 IP 头
      • 外部 IP 头用于在公网中传输数据包。
      • 源 IP 地址:左侧路由器的外网地址(172.17.10.10)。
      • 目标 IP 地址:右侧路由器的外网地址(172.16.11.10)。

    最终,封装后的数据包从左侧路由器的物理网卡(E1)发送到公共网络中。

  2. 公共网络传输
    数据包进入公共网络后,沿着公网路由器一跳一跳地转发。此时,所有的路由操作都基于外部的 IP 地址(172.17.10.10 和 172.16.11.10),GRE 头和内部 IP 头都不会被解读。

  3. 右侧路由器解封装
    数据包到达右侧路由器后,右侧路由器会检测到这是一个 GRE 包,并执行以下步骤:

    • 解封装数据包
      • 去掉外层的 IP 头和 GRE 头,恢复原始数据包。
      • 原始数据包的源 IP 地址为 192.168.1.102,目标 IP 地址为 192.168.2.115。
    • 转发到目标主机
      • 根据路由表,路由器将解封装后的数据包从接口 E3 发送到右侧的网络,最终到达主机 B。
  4. 主机 B 接收数据包
    主机 B 接收到数据包后,发现目标地址是自己的 IP 地址(192.168.2.115),于是正常处理数据包并做出响应。

  5. GRE 隧道通信的关键步骤总结

    • 封装:在发送端路由器,将数据包封装为 GRE 包,并添加外层的 IP 头,用于公网传输。
    • 传输:在公共网络中,所有路由操作基于外层的 IP 地址完成。
    • 解封装:在接收端路由器,将 GRE 包解封,恢复原始数据包。
    • 转发:根据目标 IP 地址和路由表,将数据包转发到目标主机。

这种基于 GRE 隧道的传输方式使得两个不同网段的主机能够通过公共网络安全、透明地通信,同时借助 GRE 的 Key 字段 或 NVGRE 的 网络 ID,可以实现用户流量的隔离。

优势与局限

  • 优势

    1. 支持广泛的协议封装:不仅限于 IPv4 和 IPv6,还可以封装多种其他协议,具有良好的兼容性。
    2. 灵活的租户隔离:通过 GRE 包头中的 Key 字段和 NVGRE 的网络 ID,可以轻松实现大规模云平台的租户隔离需求。
    3. 易于部署:基于现有物理网络即可实现 Overlay 网络,不需要对底层网络做大规模改造。
  • 局限

    1. 缺乏内置安全性:GRE 隧道本身不具备加密功能,数据安全需要额外借助协议(如 IPSec)来保障。
    2. 增加网络开销:封包和解包会消耗计算资源,尤其在高负载场景下可能影响性能。
    3. 隧道数量限制:GRE 是一种点对点隧道,如果有多个网络需要互联,隧道数量会呈指数增长。例如,3 个网络需要建立 3 条隧道,5 个网络需要 10 条隧道,随着网络规模增加,管理复杂性也会大幅提升。
    4. 不支持组播:当一个网络中的虚拟机发送广播帧时,GRE 会将该广播包复制并发送到所有与其相连的节点,增加了不必要的流量开销,影响效率。
    5. 兼容性问题:部分防火墙和三层网络设备无法正确解析 GRE 数据包,因此无法对其进行有效过滤或负载均衡。

VXLAN

第二种 Overlay 网络技术是 VXLAN(Virtual Extensible LAN)。与 GRE 在三层头部之外增加封装不同,VXLAN 在二层头部外直接封装了一个 VXLAN 包头。VXLAN 包头包含一个 24 位的 VXLAN ID,支持多达 16,777,216 个逻辑网络,远远超越了传统 VLAN 的 4096 个 ID 限制。在 VXLAN 包头外,还封装了 UDP、IP 和外层 MAC 头。
在这里插入图片描述

VXLAN 的核心组件:VTEP

为了实现 VXLAN 的封装和解封装,需要一种称为 VTEP(VXLAN Tunnel Endpoint) 的组件来处理 VXLAN 数据包。VTEP 类似于虚拟机网络的“管家”,负责管理虚拟机的网络连接。以下是 VTEP 的主要功能:

  1. 虚拟机注册:每台物理机上都可以有一个 VTEP,虚拟机启动时会向 VTEP 注册,VTEP 记录管理的所有虚拟机信息。
  2. 包的封装和解封装:当虚拟机需要跨 VTEP 通信时,由 VTEP 完成 VXLAN 包头的封装与解封装。
  3. 通信代理:通过 VTEP 代理机制,实现跨物理机的虚拟机通信。

与 GRE 的区别

  • 拓扑模型:GRE 是点对点的隧道,需要为每对通信的网络建立一个隧道,随着网络规模增加,隧道数量呈指数增长;而 VXLAN 支持基于组播的通信,无需每对节点单独建立隧道。
  • 动态发现:VXLAN 使用组播技术动态发现目标节点,而 GRE 通信需要明确的隧道端点。
  • 扩展性:VXLAN 的 24 位网络 ID 远超 GRE 和 VLAN 的限制,适合大规模云平台。

组播在 VXLAN 中的作用

VXLAN 利用 IGMP(Internet Group Management Protocol) 组播协议进行动态目标定位。VTEP 的组播机制类似于加入一个邮件列表或微信群:

  1. 当 VTEP 启动时,它会通过 IGMP 协议加入一个组播组,表示自己愿意接收组播流量。
  2. 当虚拟机上线并向 VTEP 注册后,VTEP 知道自己负责管理哪些虚拟机。
  3. 如果某台虚拟机发送数据包,VTEP 会将数据封装为 VXLAN 包,并根据组播组转发给目标 VTEP。所有加入该组播组的节点都会收到此消息,从而实现动态定位。

VXLAN 的优点

  1. 扩展性强:24 位的 VXLAN ID 能够支持大量虚拟网络,非常适合大规模、多租户的云平台。
  2. 动态发现目标节点:通过组播机制,无需预先配置隧道,通信更加灵活。
  3. 简化网络配置:支持二层扩展和动态地址发现,无需大规模改造物理网络。

VXLAN 的实现逻辑

当物理机上的虚拟机启动后,VTEP 立即感知到其上线,并完成以下操作:

  1. 注册虚拟机:虚拟机将自身的信息(如 IP 和 MAC 地址)注册到所在物理机的 VTEP。
  2. 加入组播组:VTEP 通过 IGMP 协议加入指定的组播组,准备接收来自其他 VTEP 的通信。
  3. 动态通信:当虚拟机发送数据包时,VTEP 封装 VXLAN 包头并利用组播将其发送到目标节点的 VTEP。
  4. 解封装与转发:目标 VTEP 解封 VXLAN 包后,将原始数据包转发到目标虚拟机。

VXLAN 的组播机制和动态发现能力使其在云平台中比 GRE 更加灵活高效,特别是在大规模、多租户环境下,能够显著降低网络管理的复杂性。
在这里插入图片描述
如图,虚拟机 1、2、3 属于云中同一个用户的虚拟机,因而需要分配相同的 VXLAN ID=101。在云的界面上,就可以知道它们的 IP 地址,于是可以在虚拟机 1 上 ping 虚拟机 2。

虚拟机 1 发现,它不知道虚拟机 2 的 MAC 地址,因而包没办法发出去,于是要发送 ARP 广播。
在这里插入图片描述
ARP 请求到达 VTEP1 的时候,VTEP1 知道,我这里有一台虚拟机,要访问一台不归我管的虚拟机,需要知道 MAC 地址,可是我不知道啊,这该咋办呢?

VTEP1 想,我不是加入了一个微信群么?可以在里面 @all 一下,问问虚拟机 2 归谁管。于是 VTEP1 将 ARP 请求封装在 VXLAN 里面,组播出去。

当然在群里面,VTEP2 和 VTEP3 都收到了消息,因而都会解开 VXLAN 包看,里面是一个 ARP。

VTEP3 在本地广播了半天,没人回,都说虚拟机 2 不归自己管。

VTEP2 在本地广播,虚拟机 2 回了,说虚拟机 2 归我管,MAC 地址是这个。通过这次通信,VTEP2 也学到了,虚拟机 1 归 VTEP1 管,以后要找虚拟机 1,去找 VTEP1 就可以了。
在这里插入图片描述
VTEP2 将 ARP 的回复封装在 VXLAN 里面,这次不用组播了,直接发回给 VTEP1。

VTEP1 解开 VXLAN 的包,发现是 ARP 的回复,于是发给虚拟机 1。通过这次通信,VTEP1 也学到了,虚拟机 2 归 VTEP2 管,以后找虚拟机 2,去找 VTEP2 就可以了。

虚拟机 1 的 ARP 得到了回复,知道了虚拟机 2 的 MAC 地址,于是就可以发送包了。
在这里插入图片描述
虚拟机 1 发给虚拟机 2 的包到达 VTEP1,它当然记得刚才学的东西,要找虚拟机 2,就去 VTEP2,于是将包封装在 VXLAN 里面,外层加上 VTEP1 和 VTEP2 的 IP 地址,发送出去。

网络包到达 VTEP2 之后,VTEP2 解开 VXLAN 封装,将包转发给虚拟机 2。

虚拟机 2 回复的包,到达 VTEP2 的时候,它当然也记得刚才学的东西,要找虚拟机 1,就去 VTEP1,于是将包封装在 VXLAN 里面,外层加上 VTEP1 和 VTEP2 的 IP 地址,也发送出去。

网络包到达 VTEP1 之后,VTEP1 解开 VXLAN 封装,将包转发给虚拟机 1。

在这里插入图片描述

GRE/VXLAN接入云平台

假设有多个物理机上的虚拟机,它们通过虚拟交换机(如 br0)进行互联,路由器和 DHCP 服务器则负责提供网络连接和地址分配。在这种网络架构中,虚拟机要访问互联网时,必须通过虚拟交换机连接到路由器,路由器再将请求通过 NAT 转发到公网。

当多个物理机上的虚拟机需要共享相同的虚拟交换机时,问题便出现了:由于物理机分布在不同的物理位置,它们的 br0 交换机可能会被切割成多个独立的段。为了解决这个问题,我们可以通过在物理机之间建立隧道,将各个虚拟交换机连接起来,使得虚拟机和路由器看起来仍然在同一个网络中。

在这个过程中,引入了 br1 这一虚拟交换机。br1 将虚拟机之间的互联和物理机之间的互联分开设计,使得网络架构更加清晰和灵活。隧道可以使用多种技术来实现,如 GRE 或 VXLAN。

当使用 OpenvSwitch 时,br0 可以借助 OpenvSwitch 提供的 Tunnel 和 Flow 功能来实现隧道通信。OpenvSwitch 支持三种类型的隧道:GRE、VXLAN 和 IPsec_GRE。利用这些技术,虚拟交换机可以成为 GRE 和 VXLAN 封装的终端,帮助有效管理和转发流量。
在这里插入图片描述
三台物理机,每台上都有两台虚拟机,分别属于两个不同的用户,因而 VLAN tag 都得打地不一样,这样才不能相互通信。但是不同物理机上的相同用户,是可以通过隧道相互通信的,因而通过 GRE 隧道可以连接到一起。

接下来,所有的 Flow Table 规则都设置在 br1 上,每个 br1 都有三个网卡,其中网卡 1 是对内的,网卡 2 和 3 是对外的。

下面我们具体来看 Flow Table 的设计。
在这里插入图片描述
1.Table 0 是所有流量的入口,所有进入 br1 的流量,分为两种流量,一个是进入物理机的流量,一个是从物理机发出的流量。

从 port 1 进来的,都是发出去的流量,全部由 Table 1 处理。

ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=1 in_port=1 actions=resubmit(,1)"

从 port 2、3 进来的,都是进入物理机的流量,全部由 Table 3 处理。

ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=1 in_port=2 actions=resubmit(,3)"
ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=1 in_port=3 actions=resubmit(,3)"

如果都没匹配上,就默认丢弃。

ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=0 actions=drop"

2.Table 1 用于处理所有出去的网络包,分为两种情况,一种是单播,一种是多播。

对于单播,由 Table 20 处理。

ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=1 table=1 dl_dst=00:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,20)"

对于多播,由 Table 21 处理。

ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=1 table=1 dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,21)"

3.Table 2 是紧接着 Table1 的,如果既不是单播,也不是多播,就默认丢弃。

ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=0 table=2 actions=drop"

4.Table 3 用于处理所有进来的网络包,需要将隧道 Tunnel ID 转换为 VLAN ID。

如果匹配不上 Tunnel ID,就默认丢弃。

ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=0 table=3 actions=drop"

如果匹配上了 Tunnel ID,就转换为相应的 VLAN ID,然后跳到 Table 10。

ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=1 table=3 tun_id=0x1 actions=mod_vlan_vid:1,resubmit(,10)"
ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=1 table=3 tun_id=0x2 actions=mod_vlan_vid:2,resubmit(,10)"
  1. 对于进来的包,Table 10 会进行 MAC 地址学习。这是一个二层交换机应该做的事情,学习完了之后,再从 port 1 发出去。
ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=1 table=10  actions=learn(table=20,priority=1,hard_timeout=300,NXM_OF_VLAN_TCI[0..11],NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],load:0->NXM_OF_VLAN_TCI[],load:NXM_NX_TUN_ID[]->NXM_NX_TUN_ID[],output:NXM_OF_IN_PORT[]),output:1"

Table 10 是用来学习 MAC 地址的,学习的结果放在 Table 20 里面。Table20 被称为 MAC learning table。

NXM_OF_VLAN_TCI 是 VLAN tag。在 MAC learning table 中,每一个 entry 都仅仅是针对某一个 VLAN 来说的,不同 VLAN 的 learning table 是分开的。在学习结果的 entry 中,会标出这个 entry 是针对哪个 VLAN 的。

NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[] 表示,当前包里面的 MAC Source Address 会被放在学习结果的 entry 里的 dl_dst 里。这是因为每个交换机都是通过进入的网络包来学习的。某个 MAC 从某个 port 进来,交换机就应该记住,以后发往这个 MAC 的包都要从这个 port 出去,因而源 MAC 地址就被放在了目标 MAC 地址里面,因为这是为了发送才这么做的。

load:0->NXM_OF_VLAN_TCI[] 是说,在 Table20 中,将包从物理机发送出去的时候,VLAN tag 设为 0,所以学习完了之后,Table 20 中会有 actions=strip_vlan。

load:NXM_NX_TUN_ID[]->NXM_NX_TUN_ID[] 的意思是,在 Table 20 中,将包从物理机发出去的时候,设置 Tunnel ID,进来的时候是多少,发送的时候就是多少,所以学习完了之后,Table 20 中会有 set_tunnel。

output:NXM_OF_IN_PORT[] 是发送给哪个 port。例如是从 port 2 进来的,那学习完了之后,Table 20 中会有 output:2。
在这里插入图片描述
所以如图所示,通过左边的 MAC 地址学习规则,学习到的结果就像右边的一样,这个结果会被放在 Table 20 里面。

6.Table 20 是 MAC Address Learning Table。如果不为空,就按照规则处理;如果为空,就说明没有进行过 MAC 地址学习,只好进行广播了,因而要交给 Table 21 处理。

ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=0 table=20 actions=resubmit(,21)"

7.Table 21 用于处理多播的包。

如果匹配不上 VLAN ID,就默认丢弃。

ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=0 table=21 actions=drop"

如果匹配上了 VLAN ID,就将 VLAN ID 转换为 Tunnel ID,从两个网卡 port 2 和 port 3 都发出去,进行多播。

ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=1table=21dl_vlan=1 actions=strip_vlan,set_tunnel:0x1,output:2,output:3"
ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=1table=21dl_vlan=2 actions=strip_vlan,set_tunnel:0x2,output:2,output:3"

总结:

  • GRE 是一种点对点的隧道模式,而 VXLAN 支持组播隧道模式。它们都需要在 Tunnel Endpoint
    进行封装和解封装,以实现跨物理机的互联。
  • OpenvSwitch 可以作为 Tunnel Endpoint,通过配置流表规则,将虚拟机网络与物理机网络进行隔离和转换,从而实现高效的跨机通信。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

上海交通大学《2024年816自动控制原理真题》 (完整版)

本文内容,全部选自自动化考研联盟的:《上海交通大学816自控考研资料》的真题篇。后续会持续更新更多学校,更多年份的真题,记得关注哦~ 目录 2024年真题 Part1:2024年完整版真题 2024年真题

零基础入门 Pyecharts 实用教程:从基础绘图到进阶技巧

简介:本文面向 Python 数据可视化初学者,脚踏实地分享 Pyecharts 库的使用经验。从查看 Pyecharts 版本起步,详细拆解绘制首个图表的全过程,涵盖导入模块、设置坐标轴、渲染 HTML 文件等基础操作;点明链式调用的版本要…

STM32 通过读取看门狗溢出标志检测程序是否发生复位

通过 __HAL_RCC_GET_FLAG 函数,读取看门狗溢出标志检测程序是否发生复位, 目录 一、__HAL_RCC_GET_FLAG 函数二、Stm32CubeMx配置三、代码编写四、运行效果 一、__HAL_RCC_GET_FLAG 函数 HAL库的 __HAL_RCC_GET_FLAG 函数可以获取到程序是否发生过看门狗…

记一次由docker容器使得服务器cpu占满密码和密钥无法访问bug

Bug场景: 前几天在服务器上部署了一个免费影视网站,这个应用需要四个容器,同时之前的建站软件workpress也是使用docker部署的,也使用了三个容器。在使用workpress之前,我将影视软件的容器全部停止。 再使用workpress…

Linx下自动化之路:Redis安装包一键安装脚本实现无网极速部署并注册成服务

目录 简介 安装包下载 安装脚本 服务常用命令 简介 通过一键安装脚本实现 Redis 安装包的无网极速部署,并将其成功注册为系统服务,开机自启。 安装包下载 redis-7.0.8.tar.gzhttp://download.redis.io/releases/redis-7.0.8.tar.gz 安装脚本 修…

开发 UEFI 驱动

服务型驱动的特点: 1)在 Image 的入口函数中执行安装; 2)服务型驱动不需要驱动特定硬件,可以安装到任意控制器上; 3)没有提供卸载函数。 一个设备 / 总线驱动程序在安装时首先要找到对应的硬件…

实现 DataGridView 下拉列表功能(C# WinForms)

本文介绍如何在 WinForms 中使用 DataGridViewComboBoxColumn 实现下拉列表功能,并通过事件响应来处理用户的选择。以下是实现步骤和示例代码。 1. 效果展示 该程序的主要功能是展示如何在 DataGridView 中插入下拉列表,并在选择某一项时触发事件。 2.…

传输层5——TCP可靠传输的实现(重点!!)

TCP协议如何实现可靠传输?确保接收方收到数据? 需要依靠几个结构: 以字节为单位的滑动窗口 这其中包括发送方的发送窗口和接收方的接收窗口 下面的描述,我们指定A为发送端口,B为接收端口 TCP的可靠传输就是靠着滑动窗口…

java Random随机数

Randoms是什么 在Java中,Random类是用于生成伪随机数的工具。它位于java.util包中。以下是一些使用Random类生成不同类型的随机数的方法: 1 创建 Random 类的实例 2 生成一个随机的int值(范围从Integer.MIN_VALUE到Integer.MAX_VALUE&#…

React的复制粘贴组件——React Copy to Clipboard

React Copy to Clipboard是一个用于在React应用程序中复制文本到剪贴板的库。它提供了一个简单的方式来实现复制到剪贴板的功能,支持多种浏览器和设备。 安装 你可以使用npm或yarn来安装React Copy to Clipboard: npm install react-copy-to-clipboa…

【Android Studio】学习——网络连接

实验:Android网络连接 文章目录 实验:Android网络连接[toc]实验目标和实验内容:1、掌握Android联网的基本概念;2、能够使用URL connection实现网络连接;3、掌握第三方库的基本概念4、需实现的具体功能 实验结果功能说明…

泷羽Sec-星河飞雪-bp验证码爆破

免责声明 学习视频来自 B 站up主泷羽sec,如涉及侵权马上删除文章。 笔记的只是方便各位师傅学习知识,以下代码、网站只涉及学习内容,其他的都与本人无关,切莫逾越法律红线,否则后果自负。 泷羽sec官网:http…

基础算法——搜索与图论

搜索与图论 图的存储方式2、最短路问题2.1、Dijkstra算法(朴素版)2.2、Dijkstra算法(堆优化版)2.3、Bellman-Ford算法2.4、SPFA求最短路2.5、SPFA判负环2.6、Floyd算法 图的存储方式 2、最短路问题 最短路问题可以分为单源最短路…

C#构造函数 析构函数 静态成员(类) 密封类 字段以及属性

每当创建类或结构的实例时,将会调用其构造函数。 类或结构可能具有采用不同参数的多个构造函数。 使用构造函数,程序员能够设置默认值、限制实例化,并编写灵活易读的代码 如果静态构造函数尚未运行,静态构造函数会在任何实例构造…

公立医院高质量发展——急慢性气道疾病药学服务科普宣传培训成功开展

2023年,为积极响应国家关于推动公立医院高质量发展的号召,中国健康促进基金会开展了公立医院高质量发展——急慢性气道疾病药学服务科普宣传培训。该项目旨在通过科普宣传和培训,提升咳喘药学规范化服务水平,促进临床专业知识与咳…

product/admin/list?page=0size=10field=jancodevalue=4562249292272

文章目录 1、ProductController2、AdminCommonService3、ProductApiService4、ProductCommonService5、ProductSqlService https://api.crossbiog.com/product/admin/list?page0&size10&fieldjancode&value45622492922721、ProductController GetMapping("ad…

linux介绍------VMWare的卸载,下载,安装------及基础命令使用

文章目录 Linux第一天1、为什么要学习linux?2、怎么去学linux?(什么是大数据)3、VMWare的卸载,下载,安装4、检查网卡5、创建新的虚拟机(安装步骤:看视频)6、几个名字的理…

游戏引擎学习第38天

仓库: https://gitee.com/mrxiao_com/2d_game 回顾上次的内容。 我们之前讨论了将精灵放在屏幕上,但颜色错误的问题。问题最终查明是因为使用了一个调整工具,导致文件的字节顺序发生了变化。重新运行“image magic”工具对一些大图像进行重新处理后&am…

leetcode 二进制数转字符串

1.题目要求: 2.题目代码: class Solution { public:string printBin(double num) {string result;double compare_value 1.0;//先给把0和.赋值给result;result.push_back(0);result.push_back(.);while(result.size() < 33){//利用十进制转换成二进制的方法//1.先给num …

JS进阶DAY3|页面加载事件和页面滚动事件

目录 一、页面加载事件 1.1 DOMContentLoaded 事件 1.1.1 触发时机 1.1.2 用途 1.1.3 代码示例document.addEventListener(DOMContentLoaded, (event) > { 1.2 load 事件 1.2.1 触发时机 1.2.2 用途 1.2.3 代码示例 二、页面滚动事件 1.1 scroll事件 1.1.1 触…