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

关于linux网桥(Linux Bridge)的一些个人记录

文章目录

    • 1. Linux Bridge简述
    • 2. 网桥创建
      • 创建
      • 配置持久化
        • 在Debian/Ubuntu系统上:
        • 在CentOS/RHEL系统上:
      • 启用和验证
    • 3. 关于linux网桥不转发ip帧的问题
      • 原因
      • 解决
      • 配置持久化
    • 4. 查看网桥学习交换表
      • 手动添加或删除条目
        • 添加条目
        • 删除条目
      • 配置静态条目
      • 设置条目的老化时间
      • 持久化配置
    • 5. 关于linux网桥STP
    • 6. 关于linux网桥不转发LLDP帧
      • 原因
      • 解决
      • 持久化配置
    • 7. 网桥vlan
      • 配置持久化
    • 8. 其他
      • 1. 网卡混杂模式配置
      • 2. 网卡接收多播包配置
      • 3. 创建VLAN接口
    • 参考链接

作为一个工业自动化行业,常游走于各种 OT 网络和 IT 网络之间的码农,linux 网桥是常使用的工具之一,每每涉及Linux 网桥, 这些记忆性的操作都要现查,零散且麻烦,所以简单整理一下,主要方便自己查询,同时分享给大家参考,希望对你有所帮助。

1. Linux Bridge简述

有了虚拟网卡,我们很自然就会联想到让网卡接入到交换机里,来实现多个容器间的相互连接。而Linux Bridge就是 Linux 系统下的虚拟化交换机,虽然它是以“网桥”(Bridge)而不是“交换机”(Switch)为名,但在使用过程中,你会发现 Linux Bridge 看起来像交换机,功能使用起来像交换机、程序实现起来也像交换机,所以它实际就是一台虚拟交换机。

Linux Bridge 是在 Linux Kernel 2.2 版本开始提供的二层转发工具,由brctl命令创建和管理。Linux Bridge 创建以后,就能够接入任何位于二层的网络设备,无论是真实的物理设备(比如 eth0),还是虚拟的设备(比如 veth 或者 tap),都能与 Linux Bridge 配合工作。当有二层数据包(以太帧)从网卡进入 Linux Bridge,它就会根据数据包的类型和目标 MAC 地址,按照如下规则转发处理:

  • 如果数据包是广播帧,转发给所有接入网桥的设备。如果数据包是单播帧,且 MAC 地址在地址转发表中不存在,则洪泛(Flooding)给所有接入网桥的设备,并把响应设备的接口与 MAC 地址学习(MAC Learning)到自己的 MAC 地址转发表中。

  • 如果数据包是单播帧,且 MAC 地址在地址转发表中已存在,则直接转发到地址表中指定的设备。

  • 如果数据包是此前转发过的,又重新发回到此 Bridge,说明冗余链路产生了环路。由于以太帧不像 IP 报文那样有 TTL 来约束,所以一旦出现环路,如果没有额外措施来处理的话,就会永不停歇地转发下去。那么对于这种数据包,就需要交换机实现生成树协议(Spanning Tree Protocol,STP)来交换拓扑信息,生成唯一拓扑链路以切断环路。

刚刚提到的这些名词,比如二层转发、泛洪、STP、MAC 学习、地址转发表,等等,都是物理交换机中已经非常成熟的概念了,它们在 Linux Bridge 中都有对应的实现,所以我才说,Linux Bridge 不仅用起来像交换机,实现起来也像交换机。

不过,它与普通的物理交换机也还是有一点差别的,普通交换机只会单纯地做二层转发,Linux Bridge 却还支持把发给它自身的数据包,接入到主机的三层协议栈中

对于通过brctl命令显式接入网桥的设备,Linux Bridge 与物理交换机的转发行为是完全一致的,它也不允许给接入的设备设置 IP 地址,因为网桥是根据 MAC 地址做二层转发的,就算设置了三层的 IP 地址也没有意义。然而,Linux Bridge 与普通交换机的区别是,除了显式接入的设备外,它自己也无可分割地连接着一台有着完整网络协议栈的 Linux 主机,因为 Linux Bridge 本身肯定是在某台 Linux 主机上创建的,我们可以看作是 Linux Bridge 有一个与自己名字相同的隐藏端口,隐式地连接了创建它的那台 Linux 主机。

因此,Linux Bridge 允许给自己设置 IP 地址,这样就比普通交换机多出了一种特殊的转发情况:如果数据包的目的 MAC 地址为网桥本身,并且网桥设置了 IP 地址的话,那该数据包就会被认为是收到发往创建网桥那台主机的数据包,这个数据包将不会转发到任何设备,而是直接交给上层(三层)协议栈去处理。这时,网桥就取代了物理网卡 eth0 设备来对接协议栈,进行三层协议的处理。

涉及工具:

sudo apt-get install bridge-utils iproute2   # 对于Debian/Ubuntu系统

2. 网桥创建

创建

创建网桥br0 并将eth0eth1 添加到网桥:

# 创建网桥 br0
sudo brctl addbr br0# 添加物理接口 eth0 到网桥
sudo brctl addif br0 eth0
sudo brctl addif br0 eth1# set up
sudo ifconfig br0 up
sudo ifconfig br0 eth0
sudo ifconfig br0 eth1

或者使用ip命令:

# 使用 ip 命令
sudo ip link add name br0 type bridge
sudo ip link set dev br0 up
sudo ip link set dev eth0 master br0
sudo ip link set dev eth1 master br0

可以使用以下命令验证网桥和接口的配置:

# 查看网桥信息
sudo bridge link show
sudo bridge fdb show br0# 或者
sudo brctl show

配置持久化

为了在系统重启后保持网桥配置,你需要将相应的配置添加到网络配置文件中。

在Debian/Ubuntu系统上:

编辑/etc/network/interfaces文件,添加如下内容:

auto br0
iface br0 inet staticaddress 192.168.1.100netmask 255.255.255.0bridge_ports eth0 eth1bridge_stp on
在CentOS/RHEL系统上:

创建或编辑/etc/sysconfig/network-scripts/ifcfg-br0文件,添加如下内容:

DEVICE=br0
TYPE=Bridge
BOOTPROTO=static
IPADDR=192.168.1.100
NETMASK=255.255.255.0
ONBOOT=yes
STP=on# 添加桥接的接口
BRIDGE_PORTS="eth0 eth1"

并确保eth0eth1的配置文件中有以下内容:

# /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
ONBOOT=yes
BRIDGE=br0# /etc/sysconfig/network-scripts/ifcfg-eth1
DEVICE=eth1
ONBOOT=yes
BRIDGE=br0

启用和验证

重新启动网络服务以应用配置:

# 对于Debian/Ubuntu
sudo systemctl restart networking# 对于CentOS/RHEL
sudo systemctl restart network

通过检查网桥状态和接口状态来验证配置:

# 查看网桥信息
sudo bridge link show
sudo bridge fdb show br0# 或者
sudo brctl show

3. 关于linux网桥不转发ip帧的问题

原因

Docker使用iptables时,默认将通过网桥的数据包发送到iptables进行处理,sysctl属性net.bridge.bridge-nf-call-iptables=1)。

这使得桥接帧(以太网,第2层)受制于iptables filter(IP,第3层),导致网桥上的3层协议通信异常。

允许{ip、ip6、arp}表看到桥接通信可以使用位于/proc/sys/net/bridge/中的适当proc条目禁用或启用:

bridge-nf-call-arptables
bridge-nf-call-iptables
bridge-nf-call-ip6tables

对应内核桥模块识别的3个“可调参数”的设置:

net.bridge.bridge-nf-call-arptables
net.bridge.bridge-nf-call-ip6tables
net.bridge.bridge-nf-call-iptables

它们控制是否将通过网桥的数据包发送到iptables进行处理。在使用网桥将虚拟机连接到网络的情况下,通常这种处理是不希望的,因为它会导致guests流量被阻止,因为主机iptables规则只考虑主机本身,而不是guests。

然而,内核中的桥模块将所有这三个值的默认值设置为“1”(“on”,即“do send the packets to iptables”),并且由于历史原因,内核维护人员拒绝更改此默认值(参见http://patchwork.ozlabs.org/patch/29319/)。

在内核拒绝了上述对编译默认值的更改之后,许多Linux发行版(包括Fedora,RHEL和CentOS)试图通过在/etc/sysctl.conf中添加行来修改编译到桥模块中的默认设置来解决这个问题:

net.bridge.bridge-nf-call-arptables = 0
net.bridge.bridge-nf-call-ip6tables = 0
net.bridge.bridge-nf-call-iptables = 0

解决

要禁用br_netfilter's代码对iptable的调用,如下所示:

sudo sysctl -w net.bridge.bridge-nf-call-iptables=0
#或者
echo 1 > /proc/sys/net/bridge/bridge-nf-call-iptables

内核(>= 5.3),在每个桥单独启用,而不是每个命名空间启用。

sudo ip link set dev br0 type bridge nf_call_iptables 1

参考链接https://wiki.libvirt.org/Net.bridge.bridge-nf-call_and_sysctl.conf.html

配置持久化

除使用最原始的脚本配置外,可以使用udev+systemd,在桥的创建(加载模块)上重写udev规则来实现。

1)在文件/etc/udev/rules.d/99-bridge.rules中:

ACTION=="add", SUBSYSTEM=="module", KERNEL=="br_netfilter", RUN+="/usr/lib/systemd/systemd-sysctl --prefix=net/bridge

2)在文件/etc/sysctl.d/bridge.conf中:

net.bridge.bridge-nf-call-arptables = 0
net.bridge.bridge-nf-call-ip6tables = 0
net.bridge.bridge-nf-call-iptables = 0

3)重新引导或重新加载udev和sysctl。

4. 查看网桥学习交换表

使用bridge命令查看网桥的学习交换表:

bridge fdb show br br0

这个命令会展示网桥br0的当前学习交换表,包括各个MAC地址和它们对应的端口。

手动添加或删除条目

添加条目

你可以手动添加一个MAC地址到网桥的学习交换表中。假设你要将MAC地址00:11:22:33:44:55绑定到接口eth0

sudo bridge fdb add 00:11:22:33:44:55 dev eth0 master br0
删除条目

同样,你可以手动删除一个MAC地址条目:

sudo bridge fdb del 00:11:22:33:44:55 dev eth0 master br0

配置静态条目

你可以配置静态条目,这样这些MAC地址永远不会从网桥的学习交换表中删除:

sudo bridge fdb add 00:11:22:33:44:55 dev eth0 

设置条目的老化时间

网桥会自动老化条目,并在一段时间不使用后删除它们。可以设置这个老化时间(以秒为单位):

sudo ip link set dev br0 type bridge ageing_time 300

这会将老化时间设置为300秒(5分钟)。

持久化配置

为了在系统重启后保持这些配置,可以将相应的命令添加到启动脚本中。例如,在Debian/Ubuntu系统中,可以将这些命令添加到/etc/network/interfaces文件中:

auto br0
iface br0 inet staticaddress 192.168.1.100netmask 255.255.255.0bridge_ports eth0 eth1post-up bridge fdb add 00:11:22:33:44:55 dev eth0 master br0 static

在CentOS/RHEL系统中,可以将命令添加到/etc/sysconfig/network-scripts/ifcfg-br0文件中:

DEVICE=br0
TYPE=Bridge
BOOTPROTO=static
IPADDR=192.168.1.100
NETMASK=255.255.255.0
ONBOOT=yes# Add these lines to the end of the file
BRIDGE_STP=no
BRIDGE_PORTS="eth0 eth1"
BRIDGE_AGEING_TIME=300# Add static FDB entries
POST_UP="bridge fdb add 00:11:22:33:44:55 dev eth0 master br0 static"

5. 关于linux网桥STP

STP的目的是防止网络环路,这可能导致网络中的流量风暴。Linux桥接从2.4和2.6内核系列开始就支持STP。要在网桥上启用STP:

sudo ip link set br0 type bridge stp_state 1
#或者
sudo brctl stp br0 on

注意:Linux网桥不支持快速生成树协议(RSTP)

网桥上显示STP阻塞状态:

sudo ip -j -p -d link show br0 | grep root_port
sudo bridge link show
#或
sudo brctl showstp br0

要更改STP call时间:

sudo ip link set br0 type bridge hello_time 300sudo ip -j -p -d link show br0 | grep \"hello_time\""hello_time": 300,

可以使用相同的基本方法来更改其他STP参数,如最大年龄、转发延迟、老化时间等

6. 关于linux网桥不转发LLDP帧

原因

IEEE为标准协议留出的范围,使用这些地址的包将被网桥过滤,而不会被转发。

IEEE 802.1D MAC Bridge Filtered MAC Group Addresses: 01-80-C2-00-00-00 to 01-80-C2-00-00-0F; MAC frames that have a destination MAC address within this range are not relayed by MAC bridges conforming to IEEE 802.1D.

IEEE协议中规定的预留的MAC地址表如下:

MAC addressProtocol
01-80-C2-00-00-00Spanning Tree (STP/RSPT/MSTP)
生成树(STP/RSPT/MSTP)
01-80-C2-00-00-01Ethernet Flow Control (pause frames)
以太网流量控制(暂停帧)
01-80-C2-00-00-02Link Aggregation Control Protocol (LACP)
链路聚合控制协议(LACP)
01-80-C2-00-00-03802.1X Port-Based Network Access Control
802.1X基于端口的网络访问控制
01-80-C2-00-00-08Provider Bridge protocols (STP)
供应商桥接协议(STP)
01-80-C2-00-00-0DProvider Bridge protocols (MVRP)
提供商桥接协议(MVRP)
01-80-C2-00-00-0E802.1AB Link Layer Discovery Protocol (LLDP)
802.1AB链路层发现协议(LLDP)

解决

综上网桥不转发LLDP(链路层发现协议)帧,但从Linux内核2.6开始,允许通过在/sys/class/net/bridge-iface/bridge/group_fwd_mask中设置特定的位掩码来控制网桥应该转发IEEE 802.1D中定义的范围内的哪些链路本地帧。默认值0表示Linux网桥不转发任何链路本地帧。

将此值设置为16384将允许网桥转发LLDP帧(01-80-C2-00-00- 0E):

# 关闭网桥的 LLDP 过滤
echo 16384 > /sys/class/net/br0/bridge/group_fwd_mask

需要注意的是,在默认的发行版本中,对于该MAC地址范围中的前三个(-00,-01,-02)是不能通过以上方式控制的, 意味着在gns3的模拟环境中,我们仍然不能成功的测试STP,流控和LACP。要克服这个限制,必须要自己编译linux kernel才行,也可以下载EVE编译好的版本,点击进入链接。这样就可以随意调整group_fwd_mask的值,支持不过滤01-80-C2-00-00-0x的所有地址了。

前文中把group_fwd_mask设为16384,对应的MAC是01-80-C2-00-00-0E,对应的协议是LLDP, 那么group_fwd_mask是如何计算的呢?

位掩码是一个16位的数字,其中第一位(最低有效位)表示MAC地址01-80-C2-00 - 00-00,第16位(最高有效位)表示01-80-C2-00-00-0F。默认值(所有位均为0)不转发任何链路本地帧。要启用特定MAC地址的帧转发,我们需要将相应的位设置为1。例如,为了允许转发LLDP帧(01-80-C2-00-00- 0E),我们需要将第15位设置为1,并将其余位保留为0:

MAC0F0E0D0C0B0A09080706050403020100
BIt0100000000000000

这意味着我们使用二进制数0100 0000 0000 0000作为位掩码,它转换为十进制数16384,就像我们在前面的例子中使用的那样。

如果我们想将LACP(01-80-C2-00-00-02)和802.1X(01-80-C2-00-00-03)添加到混合中,我们还将第3位和第4位设置为1。

MAC0F0E0D0C0B0A09080706050403020100
BIt0100000000001100

bitmasks是二进制数0100 0000 0000 1100, 转换成10进制则为16396。这样就可以允许LLDP,LACP,802.1x协议了。

按照这样的方法,要解除linux网桥对规定地址范围内所有地址的过滤,就把所有的bit都置为1 即可。

持久化配置

/etc/rc.local中添加:

#!/bin/bash# 设置网桥 br0 的组转发掩码
echo 65 > /sys/class/net/br0/bridge/group_fwd_mask
exit 0

确保脚本具有可执行权限:

sudo chmod +x /etc/rc.local

或者使用systemd 创建或编辑一个系统服务单元文件,例如/etc/systemd/system/set-group-fwd-mask.service

[Unit]
Description=Set group forward mask for bridge br0
After=network.target[Service]
Type=oneshot
ExecStart=/bin/sh -c 'echo 65 > /sys/class/net/br0/bridge/group_fwd_mask'
RemainAfterExit=yes[Install]
WantedBy=multi-user.target

启用并启动该服务:

sudo systemctl enable set-group-fwd-mask.service
sudo systemctl start set-group-fwd-mask.service

参考链接

https://interestingtraffic.nl/2017/11/21/an-oddly-specific-post-about-group_fwd_mask/

http://standards.ieee.org/develop/regauth/tut/macgrp.pdf

7. 网桥vlan

查看网桥vlan信息

bridge vlan show

要显式禁用网桥的VLAN 过滤功能,可以使用以下命令:

sudo ip link set dev br0 type bridge vlan_filtering 0

这将确保网桥br0不会处理VLAN标签

要显示VLAN流量状态,启用VLAN统计(在内核4.7中添加):

sudo ip link set br0 type bridge vlan_stats_enabled 1

前面的命令只在网桥上启用全局VLAN统计信息,并且没有细粒度地显示每个VLAN的状态。要在网桥中没有端口号时启用每个VLAN的统计信息,还需要启用vlan_stats_per_port(在内核4.20中添加)

sudo ip link set br0 type bridge vlan_stats_per_port 1

显示vlan统计信息

sudo bridge -s vlan show

配置持久化

为了在系统重启后保持配置,你需要将相应的命令添加到网络配置文件中。

在Debian/Ubuntu系统上编辑/etc/network/interfaces文件,添加如下内容:

auto br0
iface br0 inet staticaddress 192.168.1.100netmask 255.255.255.0bridge_ports eth0 eth1post-up ip link set dev br0 type bridge vlan_filtering 0

8. 其他

1. 网卡混杂模式配置

#打开混杂模式
sudo ip link set eth0 promisc on#关闭混杂模式
sudo ip link set eth0 promisc off

或者使用ifconfig

#打开混杂模式
sudo ifconfig eth0 promisc#关闭混杂模式
sudo ifconfig eth0 -promisc

2. 网卡接收多播包配置

# 确认你要配置的网络接口名称
ip link show#加入多播组
sudo ip maddr add 239.255.255.250 dev eth0#使能网卡接收多播帧
sudo ifconfig eth0 allmulti
#或
sudo ip link set dev eth0 allmulticast on#验证配置
ip maddr show dev eth0

3. 创建VLAN接口

启用802.1Q VLAN标签支持

sudo modprobe 8021q

为了使网卡能够接收所有VLAN包,你需要为每个VLAN创建虚拟接口。假设你需要接收VLAN ID为10和20的包。

sudo ip link add link eth0 name eth0.10 type vlan id 10
sudo ip link add link eth0 name eth0.20 type vlan id 20
sudo ip link set dev eth0.10 up
sudo ip link set dev eth0.20 up

或者使用 vconfig 命令创建VLAN接口(旧版命令)

sudo vconfig add eth0 10
sudo vconfig add eth0 20
sudo ifconfig eth0.10 up
sudo ifconfig eth0.20 up

你可以使用以下命令来验证VLAN接口是否已正确配置:

ip -d link show eth0.10
ip -d link show eth0.20

为了在系统重启后保持这些配置,你需要将相应的命令添加到系统启动脚本中。

在ubuntu上,编辑/etc/network/interfaces文件,添加如下内容:

auto eth0
iface eth0 inet staticaddress 192.168.1.100netmask 255.255.255.0up ip link set eth0 promisc onauto eth0.10
iface eth0.10 inet manualvlan-raw-device eth0auto eth0.20
iface eth0.20 inet manualvlan-raw-device eth0

在CentOS/RHEL系统上:

创建或编辑/etc/sysconfig/network-scripts/ifcfg-eth0文件,确保包含以下内容:

DEVICE=eth0
BOOTPROTO=none
ONBOOT=yes
PROMISC=yes

创建或编辑VLAN接口配置文件,例如/etc/sysconfig/network-scripts/ifcfg-eth0.10/etc/sysconfig/network-scripts/ifcfg-eth0.20

# /etc/sysconfig/network-scripts/ifcfg-eth0.10
DEVICE=eth0.10
BOOTPROTO=none
ONBOOT=yes
VLAN=yes# /etc/sysconfig/network-scripts/ifcfg-eth0.20
DEVICE=eth0.20
BOOTPROTO=none
ONBOOT=yes
VLAN=yes

重新启动网络服务以应用配置:

# 对于Debian/Ubuntu
sudo systemctl restart networking# 对于CentOS/RHEL
sudo systemctl restart network

参考链接

https://developers.redhat.com/articles/2022/04/06/introduction-linux-bridging-commands-and-features#vlan_filter

https://interestingtraffic.nl/2017/11/21/an-oddly-specific-post-about-group_fwd_mask/

http://standards.ieee.org/develop/regauth/tut/macgrp.pdf

https://wiki.libvirt.org/Net.bridge.bridge-nf-call_and_sysctl.conf.html

相关文章:

关于linux网桥(Linux Bridge)的一些个人记录

文章目录 1. Linux Bridge简述2. 网桥创建创建配置持久化在Debian/Ubuntu系统上:在CentOS/RHEL系统上: 启用和验证 3. 关于linux网桥不转发ip帧的问题原因解决配置持久化 4. 查看网桥学习交换表手动添加或删除条目添加条目删除条目 配置静态条目设置条目…...

黑马天机学堂学习计划模块

核心功能 系统设计思路 ​​​​​​​ 代码分析 1. 学习记录管理 • 存储学习记录到 Redis: 利用 Redis 缓存学习记录,减少频繁的数据库访问。 public void writeRecordCache(LearningRecord record) {String key String.format("LEARNING:R…...

【华为云开发者学堂】基于华为云 CodeArts CCE 开发微服务电商平台

实验目的 通过完成本实验,在 CodeArts 平台完成基于微服务的应用开发,构建和部署。 ● 理解微服务应用架构和微服务模块组件 ● 掌握 CCE 平台创建基于公共镜像的应用的操作 ● 掌握 CodeArts 平台编译构建微服务应用的操作 ● 掌握 CodeArts 平台部署微…...

小R的蛋糕分享

小R的蛋糕分享 问题描述 小R手里有一个大小为 n 行 m 列的矩形蛋糕,每个小正方形区域都有一个代表美味度的整数。小R打算切割出一个正方形的小蛋糕给自己,而剩下的部分将给小S。她希望两人吃的部分的美味度之和尽量接近。 我们定义小R吃到的部分的美味度…...

24级 秋季学期期末考试安排(专升本)

1.删除 delete 2.耐心 patience 3.设计师 designer 4.身体的 physical 5.材料,物质 material 6.极其,极端 extremely 7.摩托车 motorbike 8.城市的 urban 9.意识 awareness 10.事故 accident 16.choose B:挑选 17.prove C:证明 1…...

点击底部的 tabBar 属于 wx.switchTab 跳转方式,目标页面的 onLoad 不会触发(除非是第一次加载)

文章目录 1. tabBar 的跳转方式2. tabBar 跳转的特点3. 你的配置分析4. 生命周期触发情况5. 总结 很多人不明白什么是第一次加载,两种情况讨论,第一种情况假设我是开发者,第一次加载就是指点击微信开发者工具上边的编译按钮,每点击…...

Web枚举:深入了解目标应用系统

Web枚举是渗透测试中重要的第一步,旨在全面收集目标系统的信息,以便后续攻击载荷的构建更具针对性和效率。本文将详细讨论如何通过各种方法识别目标Web应用的技术栈,并提取关键信息。 1. 识别目标系统的技术栈 技术栈指Web应用所依赖的技术组…...

【动态规划篇】欣赏概率论与镜像法融合下,别出心裁探索解答括号序列问题

本篇鸡汤:没有人能替你承受痛苦,也没有人能拿走你的坚强. 欢迎拜访:羑悻的小杀马特.-CSDN博客 本篇主题:带你解答洛谷的括号序列问题(绝对巧解) 制作日期:2025.01.10 隶属专栏:C/C题…...

Windows Docker 安装

使用别人写好的软件/工具最大的障碍是什么——必然是配环境。配环境带来的折磨会极大地消解你对软件、编程本身的兴趣。虚拟机可以解决配环境的一部分问题,但它庞大笨重,且为了某个应用的环境配置好像也不值得模拟一个全新的操作系统。 Docker 的出现让…...

Spring 设计模式:经典设计模式

Spring 设计模式:经典设计模式 引言 Spring 框架广泛使用了经典设计模式。 这些模式在 Spring 内部发挥着重要作用。 通过理解这些设计模式在 Spring 中的应用,开发者可以更深入地掌握 Spring 框架的设计哲学和实现细节。 经典设计模式 控制反转&am…...

vscode支持ssh远程开发

文章目录 一、生成ssh使用的公钥/密钥对二、使用vscode通过ssh连接服务器1.安装插件2.配置文件3.连接服务器4.新建文件夹,存放不同的任务 三、使用scp命令与服务器互传文件、文件夹1.检查Windows 系统是否支持scp命令2.在Windows系统本地的电脑向服务器传输文件、文…...

ssh2-sftp-client和ssh2配合使用js脚本快速部署项目到服务器

有时候因为服务器不能实现github或者gitlab的自动部署服务,所以就需要使用脚本来实现自动部署,可以省时省力,一劳永逸。这里就使用ssh2-sftp-client和ssh2来实现,即便是需要sudo权限,也是可以的。 1.先将本地打包后的…...

CODESYS MODBUS TCP通信(禾川Q1 PLC作为MODBUS TCP从站)

禾川Q1 PLC MODBUS TCP 通信(PLC作为MODBUS TCP通信主站) 禾川Q1 PLC MODBUS TCP通信(CODESYS平台完整配置+代码)-CSDN博客文章浏览阅读28次。MATLAB和S7-1200PLC水箱液位高度PID控制联合仿真(MODBUSTCP通信)_将matlab仿真导入plc-CSDN博客文章浏览阅读722次。本文详细介绍了如…...

2025年第三届“华数杯”国际大学生数学建模竞赛A题题目

问题A:他能游得更快吗? 背景介绍 在2024年巴黎奥运会上,中国游泳运动员潘展乐凭借出色的表现成为全球瞩目的焦点。年仅19岁的他在男子100米自由泳比赛中以46秒40 的成绩夺冠,并创造了自己保持的世界纪录。在男子4100米混合泳接力…...

一、智能体强化学习——强化学习基础

1.1 强化学习与深度学习的基本概念 1.1.1 强化学习的核心思想 什么是强化学习? 强化学习(Reinforcement Learning, RL):指在与环境(Environment)的反复交互中,智能体(Agent&#x…...

USB学习——基本概念

文章目录 USB(Universal Serial Bus)概述USB系统的描述USB总线传输方式USB的拓扑结构 USB的连接模型USB控制器及分类USB描述符USB 端点USB枚举过程USB 四种传输类型USB 事务批量传输(Bulk)中断传输(Interrupt)等时传输(Isochronous)控制传输(Control)端点…...

vue3 初体验

git代码git clone https://github.com/kailong321200875/vue-element-plus-admin.git 后端自己写python,Django架构 1.报错:跨域,代理的方式解决 server: {port:4000, ##前端启动端口proxy: {// 选项写法/api: {target: http://127.0.0.1…...

CAPL语法基础

CAPL语法基础 目录 CAPL语法基础1. 引言2. 数据类型、变量与常量2.1 数据类型2.2 变量2.3 常量2.4 案例1:使用变量和常量计算圆的面积 3. 运算符与表达式3.1 算术运算符3.2 关系运算符3.3 逻辑运算符3.4 位运算符3.5 案例2:使用运算符实现简单的逻辑判断…...

代码的形状:重构的方向

大概2周前写了一篇《代码的形状:从外到内的探索与实践》 涵树:代码的形状:从外到内的探索与实践 觉得这个话题还可以继续,它是一个从无形到有形的过程,而这个过程感觉就是王阳明先生说的“心即理”的探寻过程。 我讨论代码的形状&#xff…...

144.《在 macOS 上安装 Redis》

文章目录 在 macOS 上安装 Redis先决条件安装在前台启动和停止 Redis使用 launchd 启动和停止 Redis连接到 Redis后续步骤Next steps redis 官方安装教程是英文,本文只是将英文文档翻译成中文,方便大家阅读 redis官方安装教程:download redis…...

使用mysql报Communications link failure异常解决

背景 线上使用polarDB,基于mysql(5.7),架构为springbootmybatisplusdurid连接池,部分业务场景涉及大表更新和查询操作,在查询慢sql且超过一定时间时就会报出"Communications link failure"异常,主要体现在界…...

搭建一个fastapi的项目,调用ollama服务

1. 项目结构 my_project/ │ ├── app/ │ ├── main.py # FastAPI应用的入口 │ ├── services/ # 包含服务逻辑 │ │ └── ollama_service.py │ ├── models/ # 定义数据模型 │ │ └── response.py │ ├─…...

【update 更新数据语法合集】.NET开源ORM框架 SqlSugar 系列

系列文章目录 🎀🎀🎀 .NET开源 ORM 框架 SqlSugar 系列 🎀🎀🎀 文章目录 系列文章目录前言 🍃一、实体对象更新1.1 单条与批量1.2 不更新某列1.3 只更新某列1.4 NULL列不更新1.5 无主键/指定列…...

Elasticsearch—索引库操作(增删查改)

Elasticsearch中Index就相当于MySQL中的数据库表 Mapping映射就类似表的结构。 因此我们想要向Elasticsearch中存储数据,必须先创建Index和Mapping 1. Mapping映射属性 Mapping是对索引库中文档的约束,常见的Mapping属性包括: type:字段数据类…...

C#进阶-在Ubuntu上部署ASP.NET Core Web API应用

随着云计算和容器化技术的普及,Linux 服务器已成为部署 Web 应用程序的主流平台之一。ASP.NET Core 作为一个跨平台、高性能的框架,非常适合在 Linux 环境中运行。本篇博客将详细介绍如何在 Linux 服务器上部署 ASP.NET Core Web API 应用,包…...

执行这个composer require topthink/think-mongo 报错

安装tp5 mongodb扩展 执行这个composer require topthink/think-mongo 报错 解决方法: 1 把composer.json里的"overtrue/wechat": "4.2.11",注释掉再执行 2 composer require topthink/think-mongo1.* 安装mongo的1版本...

大语言模型训练数据集格式

1. SFT(有监督微调)的数据集格式 对于大语言模型的训练中,SFT(Supervised Fine-Tuning)的数据集格式可以采用以下方式: 输入数据:输入数据是一个文本序列,通常是一个句子或者一个段…...

stringRedisTemplate.execute执行lua脚本

stringRedisTemplate.execute执行lua脚本 1. 引入必要依赖 确保项目中已经引入了Spring Data Redis相关依赖&#xff0c;例如在 Maven 项目中&#xff0c;一般会有如下依赖&#xff08;版本号根据实际情况调整&#xff09;&#xff1a; <dependency><groupId>or…...

鸿蒙UI(ArkUI-方舟UI框架)

参考&#xff1a;https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V13/arkts-layout-development-overview-V13 ArkUI简介 ArkUI&#xff08;方舟UI框架&#xff09;为应用的UI开发提供了完整的基础设施&#xff0c;包括简洁的UI语法、丰富的UI功能&#xff…...

Linux-蓝牙协议

SPP (Serial Port Profile): 串口协议&#xff08;SPP&#xff09;是一个蓝牙配置文件&#xff0c;允许设备通过蓝牙模拟传统的串行端口通信。它通常用于无线串口连接&#xff0c;允许设备如计算机和外设&#xff08;例如打印机或条形码扫描器&#xff09;之间进行数据传输。A…...

CES Asia 2025:科技盛宴即将开启,续写辉煌篇章

随着2025年国际消费类电子产品展览会&#xff08;CES&#xff09;在美国拉斯维加斯盛大开幕并展现出诸多令人瞩目的发展趋势&#xff0c;亚洲科技界也对即将到来的CES Asia 2025充满期待&#xff0c;一场科技盛宴即将在亚洲大陆续写辉煌。 在刚刚拉开帷幕的CES 2025上&#xff…...

tutorial3.c

这个教程程序展示了如何使用 libxlsxwriter 库向 Excel 文件中写入不同类型的数据&#xff0c;包括字符串、数字和日期。以下是程序的主要步骤和功能&#xff1a; 定义数据结构&#xff1a; 定义了一个 expense 结构体&#xff0c;包含三个成员&#xff1a;item&#xff08;项…...

C# 获取当前运行路径的6种实用方法

C# 获取当前运行路径的多种方法 在C#中&#xff0c;获取当前运行路径&#xff08;即程序的工作目录&#xff09;是常见的需求&#xff0c;尤其在处理文件读写、日志记录和配置文件时。不同的场景可能需要使用不同的方法来获取路径。本文将介绍几种常用的获取当前运行路径的方法…...

龙蜥Linux系统部署docker21.1.3版本

龙蜥系统配置docker环境 更新yum源 更新软件源中的包。 yum update安装底层工具 yum install -y yum-utils device-mapper-persistent-data lvm2添加阿里云仓库 # 添加阿里云的docker镜像仓库 yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/c…...

.NET中的框架和运行环境

在.NET生态系统中&#xff0c;框架和运行环境是两个不同的概念&#xff0c;它们各自扮演着重要的角色。 下面我将分别介绍.NET中的框架和运行环境&#xff0c;并解释它们之间的区别。 .NET 框架&#xff08;Frameworks&#xff09; 框架提供了一套预定义的类库、工具和服务&…...

STM32的存储结构

STM32F103 芯片是基于 ARM Cortex-M3 内核的微控制器&#xff0c;它集成了多种类型的存储器&#xff0c;每种存储器都有其特定的作用和存储对象。以下是关于 STM32F103 中 Flash、ROM 和 SRAM 的详细介绍&#xff1a; 1. Flash Memory (闪存) 作用&#xff1a;Flash 是非易失性…...

微信小程序

一、小程序文件结构 1.目录结构 pages文件夹&#xff1a;存放【页面文件夹】&#xff0c;一个【页面文件夹】就是一个页面&#xff0c;存放着小程序页面文件。即pages中的每一个文件夹都存放着一个小程序页面的文件&#xff08;js、wxml、json、wxss&#xff09; 页面文件夹…...

《CPython Internals》阅读笔记:p76-p95

《CPython Internals》学习第 5 天&#xff0c;p76-p95 总结&#xff0c;总计 20 页。 一、技术总结 无。 二、英语总结(生词&#xff1a;1) 1.check vi/vt. to exam sth to ensure it is correct, true, or in good condition.示例&#xff1a; (1)After I’d finished …...

HOW - Form 表单 label 和 wrapper 对齐场景

一、背景 在日常使用 表单 时&#xff0c;我们一般有如下布局&#xff1a; 可以通过 Form 表单提供的配置直接设置&#xff1a; <Formform{form}labelCol{{ span: 4 }}wrapperCol{{ span: 20 }}onFinish{handleSubmit}><Form.Itemlabel"输入框"name"…...

Js的回调函数

一、什么是回调函数&#xff08;Callback&#xff09;&#xff1f; 回调函数&#xff08;Callback Function&#xff09;是指一个函数被作为参数传递给另一个函数&#xff0c;并在特定事件发生或操作完成时执行。 可以通俗地理解为一种“委托”机制。 在JavaScript中&#xff0…...

FairGuard游戏安全2024年度报告

导 读&#xff1a;2024年&#xff0c;国内游戏市场实际销售收入3257.83亿元&#xff0c;同比增长7.53%&#xff0c;游戏用户规模6.74亿人&#xff0c;同比增长0.94%&#xff0c;市场收入与用户规模双双实现突破&#xff0c;迎来了历史新高点。但游戏黑灰产规模也在迅速扩大&…...

ant-design-vue 1.X 通过id获取a-input组件失败

1.ant-design-vue 1.X 问题描述 当我在a-form组件中&#xff0c;以v-decorator指令绑定表单组件时&#xff0c;无法根据我设置的verify-code-input获取元素 <a-input type"text" id"verify-code-input" class"paIpt":placeholder"$t(…...

JS爬虫实战演练

在这个小红书私信通里面进行一个js的爬虫 文字发送 async function sendChatMessage(content) {const url https://pro.xiaohongshu.com/api/edith/ads/pro/chat/chatline/msg;const params new URLSearchParams({porch_user_id: 677e116404ee000000000001});const messageD…...

JVM vs JDK vs JRE

JVM是Java虚拟机的缩写&#xff0c; 用于实现Java的一次编译&#xff0c;处处运行。 Java代码写成.class后&#xff0c;由本地的虚拟机运行。 JDK&#xff08;Java Development Kit&#xff09;是一个功能齐全的 Java 开发工具包&#xff0c;供开发者使用。 JDK包含了JRE。…...

OpenCV相机标定与3D重建(47)从两幅图像中的一组匹配点恢复相机的姿态(旋转和平移)函数recoverPose()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 从两幅不同相机拍摄的图像中对应的点恢复相对相机旋转和平移&#xff0c;使用手性检查。返回通过该检查的内点数量。 cv::recoverPose 是 OpenCV…...

代码随想录算法训练营day27

代码随想录算法训练营 —day27 文章目录 代码随想录算法训练营前言一、贪心算法理论基础二、455.分发饼干三、376. 摆动序列53. 最大子数组和总结 前言 今天是算法营的第27天&#xff0c;希望自己能够坚持下来&#xff01; 今日任务&#xff1a; ● 贪心算法理论基础 ● 455.…...

基于华为ENSP的OSPF状态机、工作过程、配置保姆级别详解(2)

本篇技术博文摘要 &#x1f31f; 基于华为enspOSPF状态机、OSPF工作过程、.OSPF基本配置等保姆级别具体详解步骤&#xff1b;精典图示举例说明、注意点及常见报错问题所对应的解决方法 引言 &#x1f4d8; 在这个快速发展的技术时代&#xff0c;与时俱进是每个IT人的必修课。我…...

【数据结构】链表

目录 ​编辑 1.2链表 1.2.1 链表的特性 1.2.2 单向链表 遍历无头单向链表 遍历有头单向链表 链表尾插法练习 1.2.3 单向链表的函数操作 单向链表的特点&#xff1a; 1.2链表 链表又称单链表、链式存储结构&#xff0c;用于存储逻辑关系为“一对一”的数据。 和顺序表…...

RabbitMQ解决消息积压的方法

目录 减少发送mq的消息体内容 增加消费者数量 批量消费消息 临时队列转移 监控和预警机制 分阶段实施 最后还有一个方法就是开启队列的懒加载 这篇文章总结一下自己知道的解决消息积压得方法。 减少发送mq的消息体内容 像我们没有必要知道一个的中间状态&#xff0c;只需…...

机器学习是?

机器学习&#xff08;Machine Learning&#xff09;是一门多领域交叉学科&#xff0c;涉及概率论、统计学、逼近论、凸分析、算法复杂度理论等多门学科; 是人工智能&#xff08;AI&#xff09;的一个分支&#xff0c;也是AI的核心领域&#xff0c;它专注于开发算法和模型&#…...