IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> Open vSwitch 创建拓扑 -> 正文阅读

[系统运维]Open vSwitch 创建拓扑

1. OVS 单个交换机连接两台主机

1.1. 网络拓扑

在这里插入图片描述

1.2. 实验过程

在这里插入图片描述

1.2.1. 创建一个名为 br 的OVS网桥

sudo ovs-vsctl add-br br

1.2.2. 添加端口

  1. 添加端口 p1
sudo ovs-vsctl add-port br p1 -- set Interface p1 type=internal ofport_request=10
  1. 添加端口 p2
sudo ovs-vsctl add-port br p2 -- set Interface p2 type=internal ofport_request=11

1.2.3. 创建主机

  1. 利用 Linux 网络命令空间创建终端主机 h1
sudo ip netns add h1
  1. 将之前创建好的 p1 端口链接到 h1 上
sudo ip link set p1 netns h1
  1. 为 h1 设置 ip 信息和端口
sudo ip netns exec h1 ip addr add 192.168.10.10/24 dev p1
  1. 启用混杂模式

    • 混杂模式就是接收所有经过网卡的数据包,包括不是发给本机的包,即不验证MAC地址
sudo ip netns exec h1 ifconfig p1 promisc up
  1. 按照同样的设置创建终端主机 h2
sudo ip netns del h2
sudo ip netns add h2
sudo ip link set p2 netns h2
sudo ip netns exec h2 ip addr add 192.168.10.11/24 dev p2
sudo ip netns exec h2 ifconfig p2 promisc up

1.2.4. 配置流表转发规则

sudo ovs-ofctl add-flow br in_port=10,actions=output:11
sudo ovs-ofctl add-flow br in_port=11,actions=output:10

1.2.5. 执行测试

# h1 ping h2
sudo ip netns exec h1 ping 192.168.10.11 -c 3

# h2 ping h1
sudo ip netns exec h2 ping 192.168.10.10 -c 3

1.2.6. 测试结果

在这里插入图片描述

从测试结果不难看出,主机 h1 和 h2 能够相互 ping 通,ovs 网络拓扑创建成功。

1.2.7. 完整代码

# 如果要创建的网桥已存在则先删除
sudo ovs-vsctl --if-exists del-br br
# 创建一个名为 br 的OVS网桥
sudo ovs-vsctl add-br br

# 添加端口p1
sudo ovs-vsctl add-port br p1 -- set Interface p1 type=internal ofport_request=10

# 添加端口p2
sudo ovs-vsctl add-port br p2 -- set Interface p2 type=internal ofport_request=11

# 利用Linux网络命名空间创建终端主机 h1
sudo ip netns del h1 # 如果h1已经存在则删除
sudo ip netns add h1
# 将之前创建好的p1端口链接到 h1 上
sudo ip link set p1 netns h1
# 为 h1 设置 ip 信息和端口
sudo ip netns exec h1 ip addr add 192.168.10.10/24 dev p1
# 启用混杂模式
# 混杂模式就是接收所有经过网卡的数据包,包括不是发给本机的包,即不验证MAC地址
sudo ip netns exec h1 ifconfig p1 promisc up

# 按照同样的设置创建终端主机 h2
sudo ip netns del h2
sudo ip netns add h2
sudo ip link set p2 netns h2
sudo ip netns exec h2 ip addr add 192.168.10.11/24 dev p2
sudo ip netns exec h2 ifconfig p2 promisc up

# 配置流表转发规则
sudo ovs-ofctl add-flow br in_port=10,actions=output:11
sudo ovs-ofctl add-flow br in_port=11,actions=output:10

# 执行测试
# h1 ping h2
sudo ip netns exec h1 ping 192.168.10.11 -c 3
# 输出换行
echo -e '\n'
# h2 ping h1
sudo ip netns exec h2 ping 192.168.10.10 -c 3

2. OVS 单个交换机连接三台主机

2.1. 网络拓扑

在这里插入图片描述

2.2. 创建端口和主机

sudo ovs-vsctl del-br ovs-switch
sudo ovs-vsctl add-br ovs-switch
# 端口p0
sudo ovs-vsctl add-port ovs-switch p0 -- set Interface p0 type=internal ofport_request=100

sudo ip netns del ns0
sudo ip netns add ns0
sudo ip link set p0 netns ns0
sudo ip netns exec ns0 ip addr add 192.168.1.100/24 dev p0
sudo ip netns exec ns0 ifconfig p0 promisc up # 设置网口为混杂模式

# 端口p1
sudo ovs-vsctl add-port ovs-switch p1 -- set Interface p1 type=internal ofport_request=101

sudo ip netns del ns1
sudo ip netns add ns1
sudo ip link set p1 netns ns1
sudo ip netns exec ns1 ip addr add 192.168.1.101/24 dev p1
sudo ip netns exec ns1 ifconfig p1 promisc up

# 端口p2
sudo ovs-vsctl add-port ovs-switch p2 -- set Interface p2 type=internal ofport_request=102

sudo ip netns del ns2
sudo ip netns add ns2
sudo ip link set p2 netns ns2
sudo ip netns exec ns2 ip addr add 192.168.1.102/24 dev p2
sudo ip netns exec ns2 ifconfig p2 promisc up

使用 ovs-ofctl 创建并测试 OpenFlow 命令:

2.3. 查看 OVS 信息

查看 Open vSwitch 中的端口信息。从输出结果中,可以获得交换机对应的 datapath ID (dpid),以及每个端口的 OpenFlow 端口编号,端口名称,当前状态等等。

sudo ovs-ofctl show ovs-switch

显示如下:

OFPT_FEATURES_REPLY (xid=0x2): dpid:0000bedb3ef8c74e
n_tables:254, n_buffers:0
capabilities: FLOW_STATS TABLE_STATS PORT_STATS QUEUE_STATS ARP_MATCH_IP
actions: output enqueue set_vlan_vid set_vlan_pcp strip_vlan mod_dl_src mod_dl_dst mod_nw_src mod_nw_dst mod_nw_tos mod_tp_src mod_tp_dst
 100(p0): addr:00:00:00:00:00:00
     config:     PORT_DOWN
     state:      LINK_DOWN
     speed: 0 Mbps now, 0 Mbps max
 101(p1): addr:00:00:00:00:00:00
     config:     PORT_DOWN
     state:      LINK_DOWN
     speed: 0 Mbps now, 0 Mbps max
 102(p2): addr:00:00:00:00:00:00
     config:     PORT_DOWN
     state:      LINK_DOWN
     speed: 0 Mbps now, 0 Mbps max
 LOCAL(ovs-switch): addr:be:db:3e:f8:c7:4e
     config:     PORT_DOWN
     state:      LINK_DOWN
     speed: 0 Mbps now, 0 Mbps max
OFPT_GET_CONFIG_REPLY (xid=0x4): frags=normal miss_send_len=0

这里不知道为什么三个端口(p0、p1、p2)的地址都是0,暂时没找到原因,因为看的 IBM 的那篇教程上三个地址互不相同,并且现在这篇教程已经 404 了。教程地址:https://www.ibm.com/developerworks/cn/cloud/library/1401_zhaoyi_openswitch/index.html

如果想获得网络接口的 OpenFlow 编号,也可以在 OVS 的数据库中查询:

sudo ovs-vsctl get Interface p0 ofport
# 显示结果
100

查看 datapath 的信息:

sudo ovs-dpctl show
# 显示结果
system@ovs-system:
	lookups: hit:15 missed:27 lost:0
	flows: 0
	masks: hit:24 total:0 hit/pkt:0.57
	port 0: ovs-system (internal)
	port 1: ovs-switch (internal)
	port 2: p0 (internal)
	port 3: p1 (internal)
	port 4: p2 (internal)

查看 MAC 地址:

sudo ip netns exec ns0 ping 192.168.1.100
sudo ip netns exec ns0 ping 192.168.1.101
sudo ip netns exec ns0 ping 192.168.1.102
# 然后运行
sudo ovs-appctl fdb/show ovs-switch
# 显示结果
 port  VLAN  MAC                Age
  100     0  be:d1:82:9a:82:7e   16
  101     0  f2:64:d0:67:62:0d    6
  102     0  fe:16:15:2c:5c:19    2

查看交换机所有表:

sudo ovs-ofctl dump-tables ovs-switch
# 部分显示结果
OFPST_TABLE reply (xid=0x2):
  table 0 ("classifier"):
    active=1, lookup=60, matched=60
    max_entries=1000000
    matching:
      in_port: exact match or wildcard
      eth_src: exact match or wildcard
      eth_dst: exact match or wildcard
      eth_type: exact match or wildcard
      vlan_vid: exact match or wildcard
      vlan_pcp: exact match or wildcard
      ip_src: exact match or wildcard
      ip_dst: exact match or wildcard
      nw_proto: exact match or wildcard
      nw_tos: exact match or wildcard
      tcp_src: exact match or wildcard
      tcp_dst: exact match or wildcard

  table 1 ("table1"):
    active=0, lookup=0, matched=0
    (same features)

查看交换机中所有的流表项:

sudo ovs?ofctl dump?flows ovs-switch
# 显示结果
 cookie=0x0, duration=437.874s, table=0, n_packets=60, n_bytes=4712, priority=0 actions=NORMAL

删除编号为 100 的端口上的所有流表项:

sudo ovs-ofctl del-flows ovs-switch "in_port=100"

2.4. 修改数据包

屏蔽所有进入 OVS 的以太网广播数据包:

sudo ovs-ofctl add-flow ovs-switch "table=0, dl_src=01:00:00:00:00:00/01:00:00:00:00:00, actions=drop"

屏蔽 STP 协议的广播数据包:

sudo ovs-ofctl add-flow ovs-switch "table=0, dl_dst=01:80:c2:00:00:00/ff:ff:ff:ff:ff:f0, actions=drop"

修改数据包,添加新的 OpenFlow 条目,修改从端口 p0 收到的数据包的源地址为 9.181.137.1

sudo ovs-ofctl add-flow ovs-switch "priority=1 idle_timeout=0,in_port=100,actions=mod_nw_src:9.181.137.1,normal"

从端口 p0(192.168.1.100)发送测试数据到端口 p1(192.168.1.101),但是没啥相应。

sudo ip netns exec ns0 ping 192.168.1.101

再打开一个ssh终端,登录进去,运行 tcpdump,发现接收到的数据包的来源已经被修改为 9.181.137.1。(需要等待几分钟,才能看到响应)

sudo ip netns exec ns1 tcpdump -i p1 icmp
# 显示部分结果
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on p1, link-type EN10MB (Ethernet), capture size 262144 bytes
11:13:09.319092 IP 9.181.137.1 > MininetWiFi: ICMP echo request, id 3620, seq 38, length 64
11:13:10.343063 IP 9.181.137.1 > MininetWiFi: ICMP echo request, id 3620, seq 39, length 64

在这里会发现无法ping通,查了一下资料,大概原因是网络中没有控制器,交换机不知道该干什么,需要手动为 OVS 添加流表转发规则,如下:

sudo ovs-ofctl add-flow ovs-switch in_port=100,actions=output:101
sudo ovs-ofctl add-flow ovs-switch in_port=101,actions=output:100

重定向数据包

添加新的 OpenFlow 条目,重定向所有的 ICMP 数据包到端口 p2:

sudo ovs-ofctl add-flow ovs-switch idle_timeout=0,dl_type=0x0800,nw_proto=1,actions=output:102

从端口 p0 (192.168.1.100)发送数据到端口 p1(192.168.1.101)

sudo ip netns exec ns0 ping 192.168.1.101

在端口 p2 上监控数据,发现数据包已被转发到端口 p2(可能要等几分钟)

sudo ip netns exec ns2 tcpdump -i p2 icmp
# 显示部分结果
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on p2, link-type EN10MB (Ethernet), capture size 262144 bytes
11:18:52.935709 IP 192.168.1.100 > 192.168.1.101: ICMP echo request, id 3668, seq 26, length 64
11:18:53.960649 IP 192.168.1.100 > 192.168.1.101: ICMP echo request, id 3668, seq 27, length 64
11:18:54.983723 IP 192.168.1.100 > 192.168.1.101: ICMP echo request, id 3668, seq 28, length 64

2.5. 修改数据包的 VLAN Tag

除了使用 pingtcpdumpiperf 等 Linux 命令以外,也可以使用 OVS 提供的 ovs-appctl ofproto/trace 工具来测试 OVS 对数据包的转发状况。ovs-appctl ofproto/trace 可以用来生成测试用的模拟数据包,并一步步的展示 OVS 对数据包的流处理过程。在以下的例子中,演示一下如何使用这个命令:

修改端口 p1 的 VLAN tag 为 101,使端口 p1 成为一个隶属于 VLAN 101 的端口:

sudo ovs-vsctl set Port p1 tag=101

现在由于端口 p0 和 p1 属于不同的 VLAN,它们之间无法进行数据交换。使用 ovs-appctl ofproto/trace 生成一个从端口 p0 发送到端口 p1 的数据包,这个数据包不包含任何 VLAN tag,并观察 OVS 的处理过程:

sudo ovs-appctl ofproto/trace ovs-switch in_port=100,dl_src=be:d1:82:9a:82:7e,dl_dst=f2:64:d0:67:62:0d -generate

注意:上面第一个 MAC地址是 p0 的,第二个 MAC 地址是 p1 的。

显示结果:

Flow: in_port=100,vlan_tci=0x0000,dl_src=be:d1:82:9a:82:7e,dl_dst=f2:64:d0:67:62:0d,dl_type=0x0000

bridge("ovs-switch")
--------------------
 0. in_port=100, priority 1
    mod_nw_src:9.181.137.1
    NORMAL
     -> no learned MAC for destination, flooding

Final flow: unchanged
Megaflow: recirc_id=0,eth,in_port=100,vlan_tci=0x0000/0x1fff,dl_src=be:d1:82:9a:82:7e,dl_dst=f2:64:d0:67:62:0d,dl_type=0x0000
Datapath actions: 1,4

  • 在第一行输出中:Flow: 之后的字段描述了输入的流的信息。由于没有指定太多信息,所以多数字段 (例如 dl_typevlan_tci)被 OVS 设置为空值。

  • bridge("ovs-switch") 下面的第一项描述了匹配成功的流表项。

  • 在接下来的一行输出中描述了实际执行的操作。

  • 最后一段以 Final flow: 开始的字段是整个处理过程的总结,Datapath actions: 4,1 代表数据包被发送到 datapath 的 4 和 1 号端口。

创建一条新的 Flow:对于从端口 p0 进入交换机的数据包,如果它不包含任何 VLAN tag,则自动为它添加 VLAN tag 101。

sudo ovs-ofctl add-flow ovs-switch "priority=3,in_port=100,dl_vlan=0xffff,actions=mod_vlan_vid:101,normal"

再次尝试从端口 p0 发送一个不包含任何 VLAN tag 的数据包,发现数据包进入端口 p0 之后, 会被加上 VLAN tag101, 同时转发到端口 p1 上。

sudo ovs-appctl ofproto/trace ovs-switch in_port=100,dl_src=be:d1:82:9a:82:7e,dl_dst=f2:64:d0:67:62:0d -generate

输出结果

Flow: in_port=100,vlan_tci=0x0000,dl_src=be:d1:82:9a:82:7e,dl_dst=f2:64:d0:67:62:0d,dl_type=0x0000

bridge("ovs-switch")
--------------------
 0. in_port=100,vlan_tci=0x0000, priority 3
    mod_vlan_vid:101
    NORMAL
     -> learned that be:d1:82:9a:82:7e is on port p0 in VLAN 101
     -> no learned MAC for destination, flooding

Final flow: in_port=100,dl_vlan=101,dl_vlan_pcp=0,vlan_tci1=0x0000,dl_src=be:d1:82:9a:82:7e,dl_dst=f2:64:d0:67:62:0d,dl_type=0x0000
Megaflow: recirc_id=0,eth,in_port=100,vlan_tci=0x0000,dl_src=be:d1:82:9a:82:7e,dl_dst=f2:64:d0:67:62:0d,dl_type=0x0000
Datapath actions: push_vlan(vid=101,pcp=0),1,pop_vlan,3,push_vlan(vid=101,pcp=0),4

反过来从端口 p1 发送数据包,由于 p1 现在是带有 VLAN tag 101 的 Access 类型的端口,所以数据包进入端口 p1 之后,会被 OVS 添加 VLAN tag 101 并发送到端口 p0

sudo ovs-appctl ofproto/trace ovs-switch in_port=101,dl_dst=f2:64:d0:67:62:0d,dl_src=be:d1:82:9a:82:7e -generate

显示结果:

Flow: in_port=101,vlan_tci=0x0000,dl_src=be:d1:82:9a:82:7e,dl_dst=f2:64:d0:67:62:0d,dl_type=0x0000

bridge("ovs-switch")
--------------------
 0. priority 0
    NORMAL
     -> learned that be:d1:82:9a:82:7e is on port p1 in VLAN 101
     -> learned port is input port, dropping

Final flow: unchanged
Megaflow: recirc_id=0,eth,in_port=101,vlan_tci=0x0000/0x1fff,dl_src=be:d1:82:9a:82:7e,dl_dst=f2:64:d0:67:62:0d,dl_type=0x0000
Datapath actions: drop

参考:基于 Open vSwitch 的 OpenFlow 实践

3. OVS 两个交换机

参考《重构网络,SDN架构与实现》这本书。


预期构建的网络拓扑图如下所示。

在这里插入图片描述

3.1. 创建 OVS 交换机实例

sudo ovs-vsctl --if-exists del-br s1
sudo ovs-vsctl --if-exists del-br s2
sudo ovs-vsctl add-br s1
sudo ovs-vsctl add-br s2

3.2. 添加端口

在创建 OVS 实例时,会自动创建 LOCAL 端口,名称和交换机一致。为了实现通信,还需要创建其他的数据端口。没有端口汇聚的情况下,port 和 interface 是一一对应的。创建端口之后,需要对端口/接口的端口号等特性进行配置,比如设置 OpenFlow 端口号为 10。将端口设置为 Internal 模式,从而在系统中创建一个虚拟的网络设备。

sudo ovs-vsctl add-port s1 p1 -- set Interface p1 type=internal ofport_request=10
# ethtool -i p1

sudo ovs-vsctl add-port s1 p2 -- set Interface p2 type=internal ofport_request=11
# ethtool -i p2

sudo ovs-vsctl add-port s2 p3 -- set Interface p3 type=internal ofport_request=1
# ethtool -i p3

sudo ovs-vsctl add-port s2 p4 -- set Interface p4 type=internal ofport_request=2
# ethtool -i p4

3.3. 创建命名空间

为了不影响网络中已有地址发生冲突,需要创建 Namespace 作为实验的终端主机。创建主机之后,需要为其设置虚拟 IP,最后将其连接到 OVS 的数据端口,完成主机接入工作。本实验中,创建了 h1 和 h2 两个虚拟主机,设置 IP 分别为 192.168.10.10 和 192.168.10.11,并将这两个主机分别接入到两个 OVS 实例上。

sudo ip netns del h1
sudo ip netns add h1
sudo ip link set p1 netns h1
sudo ip netns exec h1 ip addr add 192.168.10.10/24 dev p1
sudo ip netns exec h1 ifconfig p1 promisc up

同理创建 h2,并设置 IP 为 192.168.10.11 并将其接入到 s2 的 p4 端口上。

sudo ip netns del h2
sudo ip netns add h2
sudo ip link set p4 netns h2
sudo ip netns exec h2 ip addr add 192.168.10.11/24 dev p4
sudo ip netns exec h2 ifconfig p4 promisc up

接下来,建立交换机之间的链路。首先,需要将对应的端口设置为 patch 类型。

sudo ovs-vsctl set interface p2 type=patch
sudo ovs-vsctl set interface p3 type=patch

然后,需要创建 p2 到 p3 的内部链路,命令如下。

sudo ovs-vsctl set interface p2 options:peer=p3
sudo ovs-vsctl set interface p3 options:peer=p2

3.4. 添加流表项

最后,需要向交换机添加对应的流表项,将交换机 s1 从 10 端口进入的数据转发到 11 端口,反向同理,s2 操作同 s1,具体操作如下。

sudo ovs-ofctl add-flow s1 in_port=10,actions=output:11
sudo ovs-ofctl add-flow s1 in_port=11,actions=output:10
sudo ovs-ofctl add-flow s2 in_port=2,actions=output:1
sudo ovs-ofctl add-flow s2 in_port=1,actions=output:2

3.5. 测试结果

创建成功,在 Network Namespace h1 环境下执行 sudo ip netns exec h1 ping 192.168.10.11 -c 3 的操作,结果成功,如下所示。

在这里插入图片描述

3.6. 完整代码

sudo ovs-vsctl --if-exists del-br s1
sudo ovs-vsctl --if-exists del-br s2
sudo ovs-vsctl add-br s1
sudo ovs-vsctl add-br s2

sudo ovs-vsctl add-port s1 p1 -- set Interface p1 type=internal ofport_request=10
# ethtool -i p1
sudo ovs-vsctl add-port s1 p2 -- set Interface p2 type=internal ofport_request=11
# ethtool -i p2
sudo ovs-vsctl add-port s2 p3 -- set Interface p3 type=internal ofport_request=1
# ethtool -i p3
sudo ovs-vsctl add-port s2 p4 -- set Interface p4 type=internal ofport_request=2
# ethtool -i p4

sudo ip netns del h1
sudo ip netns add h1
sudo ip link set p1 netns h1
sudo ip netns exec h1 ip addr add 192.168.10.10/24 dev p1
sudo ip netns exec h1 ifconfig p1 promisc up

sudo ip netns del h2
sudo ip netns add h2
sudo ip link set p4 netns h2
sudo ip netns exec h2 ip addr add 192.168.10.11/24 dev p4
sudo ip netns exec h2 ifconfig p4 promisc up

sudo ovs-vsctl set interface p2 type=patch
sudo ovs-vsctl set interface p3 type=patch

sudo ovs-vsctl set interface p2 options:peer=p3
sudo ovs-vsctl set interface p3 options:peer=p2

sudo ovs-ofctl add-flow s1 in_port=10,actions=output:11
sudo ovs-ofctl add-flow s1 in_port=11,actions=output:10
sudo ovs-ofctl add-flow s2 in_port=2,actions=output:1
sudo ovs-ofctl add-flow s2 in_port=1,actions=output:2

sudo ip netns exec h1 ping 192.168.10.11 -c 3
do ip link set p4 netns h2
sudo ip netns exec h2 ip addr add 192.168.10.11/24 dev p4
sudo ip netns exec h2 ifconfig p4 promisc up

sudo ovs-vsctl set interface p2 type=patch
sudo ovs-vsctl set interface p3 type=patch

sudo ovs-vsctl set interface p2 options:peer=p3
sudo ovs-vsctl set interface p3 options:peer=p2

sudo ovs-ofctl add-flow s1 in_port=10,actions=output:11
sudo ovs-ofctl add-flow s1 in_port=11,actions=output:10
sudo ovs-ofctl add-flow s2 in_port=2,actions=output:1
sudo ovs-ofctl add-flow s2 in_port=1,actions=output:2

sudo ip netns exec h1 ping 192.168.10.11 -c 3
  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2022-03-21 21:35:42  更:2022-03-21 21:37:24 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/26 2:34:44-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计