
简介本资源是一份面向计算机网络专业本科生及实验教学人员的Mininet网络仿真实践指南聚焦OpenFlow协议理解与SDN环境搭建解决传统网络实验缺乏真实设备、拓扑调整困难等痛点。文档以PDF格式呈现共1个文件大小1.18MB内容涵盖VMware虚拟机中Mininet环境部署、X11图形转发配置、Wireshark抓包分析OpenFlow控制流、CLI常用命令nodes/net/dump/pingall、多类型拓扑构建single/linear/custom、链路参数调优延迟、带宽、MAC固定、xterms调试技巧及回归测试pingpair/iperf/pingall等完整实验链条。预览显示其结构清晰分章对应需求分析、环境搭建、命令实操、拓扑定制与进阶调试每步均附可执行命令与预期输出说明。目前已有545人学习下载适合课堂实验预习、课设实施与自学复现提供即开即用的标准化实验路径与排错依据。1. Mininet 实验课设不是装个软件就能跑通的“网络黑匣子”而是把 TCP/IP 协议栈塞进内存里跑的实时沙盒你拿到《计算机网络 mininet 实验课设.pdf》那一刻大概率正对着终端里一行sudo mn --topo single,3 --controller remote报错发呆——明明文档说“开箱即用”结果连最简单的拓扑都起不来或者刚配好 OpenFlow 流表h1 ping h2却卡在Destination Host UnreachableWireshark 抓包里连 ARP 请求都没发出去又或者实验报告写到“验证 TCP 拥塞控制”但iperf3 -c 10.0.0.2 -t 30跑出来的吞吐量曲线平得像尺子根本看不出 Reno 和 Cubic 的区别。这不是你手残是 Mininet 从不承诺“一键仿真”——它本质是用 Python 进程 Linux network namespace veth pair OpenFlow 虚拟交换机在单机内存里硬生生克隆出一个可编程、可调试、可断点的微型互联网。它不模拟协议逻辑而是真实执行 Linux 内核的 TCP 栈、真实转发 OpenFlow 规则、真实触发 netfilter 钩子。所以课设不是考你会不会打命令而是考你能不能看懂mn -v输出里每一行进程 PID 对应哪个命名空间、为什么ovs-ofctl dump-flows s1看不到流表却ovs-ofctl show s1显示端口 up、以及tc qdisc add dev s1-eth1 root tbf rate 10mbit burst 32kbit latency 10ms这条命令里burst设小了会导致 ICMP echo reply 直接被丢弃。适合两类人一类是想甩开 Cisco Packet Tracer/ENSP 的图形拖拽真正摸清SYN → SYN-ACK → ACK在内核 sk_buff 里怎么流转的硬核学习者另一类是期末前 48 小时要交三份不同拓扑树形/环形/带防火墙 流量调度 QoS 验证的赶工党——本文就按后者的真实节奏来拆解所有命令、参数、报错截图级还原。2. 从零部署 Mininet别碰 Ubuntu 官方源用官方 deb 包 手动编译内核模块才是稳态基线Mininet 表面是个 Python 工具底层却和 Linux 内核深度耦合。Ubuntu 22.04 自带的mininet包版本 2.3.0d7默认禁用openvswitch内核模块且ovs-kmod版本与用户态ovs-vswitchd不匹配导致mn --topo linear,4 --controller remote启动后s1交换机始终is_connected: false。这不是配置问题是内核模块没加载。必须放弃apt install mininet走官方 deb 包 手动编译路径。2.1 下载并安装 Mininet 官方 deb 包非 apt 源Mininet 官网mininet.github.io明确要求使用其发布的.deb包而非发行版仓库。截至 2024 年稳定课设推荐版本为Mininet 2.3.0d7对应 Open vSwitch 2.17该版本对 Linux 5.15 内核兼容性最佳且自带ovs-kmod编译脚本# 创建临时工作目录 mkdir ~/mininet-install cd ~/mininet-install # 下载官方 deb 包注意必须用 curl -L否则重定向失败 curl -L https://github.com/mininet/mininet/releases/download/2.3.0d7/mininet-2.3.0d7-1-amd64.deb -o mininet-2.3.0d7-1-amd64.deb # 安装 deb 包会自动解决 python3 依赖 sudo dpkg -i mininet-2.3.0d7-1-amd64.deb # 修复可能缺失的依赖尤其 libssl1.1 在 Ubuntu 22.04 已移除 sudo apt --fix-broken install -y提示dpkg -i后若提示libssl1.1:amd64 is not installed不要强行apt install libssl1.1该库在 Ubuntu 22.04 已废弃。正确做法是下载libssl1.1兼容包wget http://archive.ubuntu.com/ubuntu/pool/main/o/openssl/libssl1.1_1.1.1f-1ubuntu2.19_amd64.deb sudo dpkg -i libssl1.1_1.1.1f-1ubuntu2.19_amd64.deb2.2 编译并加载 Open vSwitch 内核模块Mininet 默认不启用 OVS 内核加速模块openvswitch.ko导致所有数据包走用户态ovs-vswitchd吞吐量低于 100Mbps 且延迟抖动大无法支撑iperf3压测或 TCP 拥塞算法对比实验。必须手动编译加载# 进入 Mininet 源码目录deb 包已自带 cd /usr/share/mininet # 编译内核模块需 kernel headers sudo make modules # 加载模块关键 sudo modprobe openvswitch # 验证模块是否加载成功 lsmod | grep openvswitch # 应输出 openvswitch 229376 0编译过程会检查当前内核版本uname -r若提示Kernel headers not found需安装对应头文件# Ubuntu 22.04 示例根据 uname -r 动态替换 sudo apt install linux-headers-$(uname -r) -y2.3 验证基础拓扑连通性最小可行命令完成上述两步后用最简命令验证环境是否真正就绪# 启动单交换机三主机拓扑启用详细日志 sudo mn --topo single,3 --controller remote --switch ovs --ipbase 10.0.0.0/24 -v # 在 Mininet CLI 中执行注意必须等所有节点 READY 后再输入 mininet h1 ifconfig h1-eth0 # 查看 h1 IP应为 10.0.0.1 mininet h2 ifconfig h2-eth0 # 应为 10.0.0.2 mininet h1 ping -c 3 h2 # 必须看到 3/3 success且 time 1ms关键参数说明--switch ovs强制使用 Open vSwitch 而非默认的ovskernel内核态 OVS这是课设中流表编程的前提--ipbase 10.0.0.0/24显式指定子网避免 Mininet 自动分配10.0.0.0/8导致后续iperf3端口冲突-v启用 verbose 日志启动时会打印每个 namespace 的 PID、veth pair 名称如s1-eth1↔h1-eth0这是排查连通性问题的第一手线索。若ping失败立即执行sudo mn -c清理残留 namespace再检查dmesg | tail -20是否有openvswitch: could not create datapath错误——这表明内核模块未加载或版本不匹配。3. 课设核心拓扑构建用 Python 脚本替代 CLI 命令让树形/环形/带防火墙拓扑可复现、可参数化课设 PDF 里常要求实现“三层树形拓扑”“含冗余链路的环形拓扑”“接入防火墙的 DMZ 区域”。如果每次都手敲mn --topo tree,depth3,fanout2不仅易错更无法嵌入流量生成、流表下发、QoS 配置等后续步骤。必须用 Mininet 的 Python API 编写可复用脚本且每个拓扑需满足三个硬性条件IP 可预测、交换机可编程、主机可注入流量。3.1 树形拓扑脚本支持 depth/fanout 参数化#!/usr/bin/env python3 tree_topo.py可参数化的三层树形拓扑 - 根交换机 s1 连接 2 个汇聚交换机 s2/s3 - 每个汇聚交换机连接 2 台主机h1-h2 属 s2h3-h4 属 s3 - 所有主机 IP 固定h110.0.1.1, h210.0.1.2, h310.0.2.1, h410.0.2.2 from mininet.topo import Topo from mininet.net import Mininet from mininet.node import OVSSwitch, RemoteController from mininet.cli import CLI from mininet.log import setLogLevel class TreeTopo(Topo): def build(self, depth2, fanout2): # 创建根交换机 s1 self.addSwitch(s1) # 构建 depth 层每层 fanout 分支 for i in range(fanout): # 汇聚层交换机 s2 self.addSwitch(fs2{i1}) self.addLink(s1, s2) # 接入层主机每台主机固定 IP for j in range(fanout): host_num i * fanout j 1 ip_suffix f{i1}.{j1} h self.addHost(fh{host_num}, ipf10.0.{ip_suffix}.1/24) self.addLink(s2, h) if __name__ __main__: setLogLevel(info) topo TreeTopo(depth2, fanout2) # 生成 4 主机拓扑 net Mininet(topotopo, switchOVSSwitch, controllerRemoteController(c0, ip127.0.0.1, port6633), autoSetMacsTrue) net.start() # 为每台主机设置默认路由指向其直连交换机 for host in net.hosts: host.cmd(ip route add default via 10.0.%s.254 % host.IP().split(.)[2]) CLI(net) net.stop()执行与验证sudo python3 tree_topo.py # 在 CLI 中执行 mininet h1 ping -c 2 h4 # 跨子网通信应通经 s1 中转 mininet h1 arp -a # 查看 ARP 表h1 应有 s21 的 MAC10.0.1.254注意host.cmd(ip route add ...)是关键。Mininet 默认不配置跨子网路由必须手动为每台主机添加默认网关指向其直连交换机的管理 IP。此处约定交换机管理 IP 为10.0.X.254X 为子网号需在后续流表下发时确保该 IP 可达。3.2 环形拓扑脚本含 STP 防环验证环形拓扑是课设高频需求如“验证 RSTP 收敛时间”但 Mininet 默认不启用 STP需手动开启 OVS 的 STP 功能#!/usr/bin/env python3 ring_topo.py四节点环形拓扑启用 STP 防环 - 交换机 s1-s4 成环每台连接 1 台主机 - 启用 STP 后s2-s3 链路应被阻塞BPDU 投票 from mininet.topo import Topo from mininet.net import Mininet from mininet.node import OVSSwitch, RemoteController from mininet.cli import CLI from mininet.log import setLogLevel class RingTopo(Topo): def build(self): switches [] hosts [] # 创建 4 台交换机 for i in range(1, 5): s self.addSwitch(fs{i}) switches.append(s) # 创建 4 台主机 for i in range(1, 5): h self.addHost(fh{i}, ipf10.0.0.{i}/24) hosts.append(h) # 连接成环s1-s2, s2-s3, s3-s4, s4-s1 for i in range(4): self.addLink(switches[i], switches[(i1)%4]) self.addLink(switches[i], hosts[i]) if __name__ __main__: setLogLevel(info) topo RingTopo() net Mininet(topotopo, switchOVSSwitch, controllerRemoteController(c0, ip127.0.0.1, port6633)) net.start() # 为每台交换机启用 STP必须在 net.start() 后执行 for switch in net.switches: switch.cmd(ovs-vsctl set bridge {} stp_enabletrue.format(switch.name)) # 验证 STP 状态s2 的 s2-s3 端口应为 blocking s2 net.get(s2) print(s2 STP status:) s2.cmdPrint(ovs-ofctl dump-ports-desc s2 | grep -A 5 s2-s3) CLI(net) net.stop()STP 验证要点ovs-vsctl set bridge s2 stp_enabletrue必须在net.start()之后执行否则配置不生效ovs-ofctl dump-ports-desc s2输出中s2-s3端口的state字段应为0x20即OFPPS_STP_BLOCK表示被 STP 阻塞若ping h1 h3仍通说明 STP 未生效——检查ovs-vsctl get bridge s2 stp_enable是否返回true及ovs-vsctl list stp是否显示实例。3.3 带防火墙的 DMZ 拓扑iptables netfilter 链课设常要求“在边界部署防火墙仅允许 HTTP 访问 Web 服务器”。Mininet 中防火墙即运行iptables的 Linux 主机需在主机启动时预加载规则#!/usr/bin/env python3 dmz_topo.py含防火墙的 DMZ 拓扑 - h1: 内网客户端10.0.1.1 - h2: 防火墙双网卡eth010.0.1.254, eth110.0.2.254 - h3: Web 服务器10.0.2.1仅开放 80 端口 from mininet.topo import Topo from mininet.net import Mininet from mininet.node import Host, OVSSwitch, RemoteController from mininet.cli import CLI from mininet.log import setLogLevel class DMZTopo(Topo): def build(self): # 内网主机 h1 self.addHost(h1, ip10.0.1.1/24) # 防火墙主机双网卡 fw self.addHost(fw, ip10.0.1.254/24) # DMZ 主机 h3 self.addHost(h3, ip10.0.2.1/24) # 交换机 s1 self.addSwitch(s1) s2 self.addSwitch(s2) # 连接 self.addLink(h1, s1) self.addLink(fw, s1) # fw eth0 接 s1 self.addLink(fw, s2) # fw eth1 接 s2 self.addLink(h3, s2) if __name__ __main__: setLogLevel(info) topo DMZTopo() net Mininet(topotopo, switchOVSSwitch, controllerRemoteController(c0, ip127.0.0.1, port6633)) net.start() # 配置防火墙启用 IP 转发 iptables 规则 fw net.get(fw) fw.cmd(sysctl -w net.ipv4.ip_forward1) # 开启转发 # 清空默认规则 fw.cmd(iptables -P INPUT ACCEPT) fw.cmd(iptables -P FORWARD ACCEPT) fw.cmd(iptables -F) # 仅允许 h1 → h3:80拒绝其他 fw.cmd(iptables -A FORWARD -i h1-eth0 -o h3-eth0 -p tcp --dport 80 -j ACCEPT) fw.cmd(iptables -A FORWARD -i h3-eth0 -o h1-eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT) fw.cmd(iptables -A FORWARD -j DROP) # 启动 Web 服务Python 简易 HTTP Server h3 net.get(h3) h3.cmd(python3 -m http.server 80 ) CLI(net) net.stop()防火墙验证命令mininet h1 curl -I http://10.0.2.1 # 应返回 HTTP/1.0 200 OK mininet h1 telnet 10.0.2.1 22 # 应超时SSH 被 DROP mininet fw iptables -L FORWARD -v # 查看命中计数器确认规则生效关键细节iptables -A FORWARD规则作用于fw主机的FORWARD链因h1→h3流量经过fw的两个网卡h1-eth0→h3-eth0属于转发行为。-m state --state ESTABLISHED,RELATED确保响应包能回传这是无状态防火墙的常见疏漏点。4. 流量调度与 QoS 实验用 tc netem 精确控制带宽/延迟/丢包而不是靠iperf3 -u -b猜课设报告常要求“验证不同队列机制FIFO/PFIFO_FAST/SFQ对 TCP 吞吐量的影响”但若只用iperf3 -c h2 -t 30得到的是平均吞吐量无法体现瞬时抖动、突发丢包对拥塞窗口的影响。必须用tctraffic control在交换机端口上注入可控损伤再用ping/mtr/tcpdump多维度观测。4.1 在交换机端口上部署 tc qdisc以 s1-eth1 为例Mininet 中交换机端口对应 Linux 的veth设备如s1-eth1可在其上直接应用tc# 获取 s1-eth1 的真实设备名在 host namespace 中 sudo ip link show | grep s1-eth1 # 输出类似23: s1-eth1if22: BROADCAST,MULTICAST,UP # 在 s1 的 network namespace 中执行需先找到 s1 的 PID sudo nsenter -t $(pgrep -f ovs-vswitchd.*s1) -n \ tc qdisc add dev s1-eth1 root tbf rate 5mbit burst 32kbit latency 100ms参数血泪经验rate 5mbit硬限速超过此速率的包会被缓存或丢弃burst 32kbit突发缓冲区大小必须 ≥ TCP 初始 cwnd通常 10 MSS ≈ 14KB否则 SYN 包就被丢导致连接超时latency 100ms最大排队延迟若burst/rate计算出的理论延迟 此值多余包将被丢弃tbf的 tail-drop 行为。验证是否生效# 在 h1 上 ping h2观察延迟是否稳定在 100±5ms h1 ping -c 5 h2 | awk {print $7} | grep time | cut -d -f2 # 应输出类似102.3 ms, 101.8 ms, ...4.2 模拟丢包与乱序netem 模块tbf只能限速要模拟网络损伤需用netem# 在 s1-eth1 上添加 netem注意需先删除 tbf sudo nsenter -t $(pgrep -f ovs-vswitchd.*s1) -n \ tc qdisc del dev s1-eth1 root sudo nsenter -t $(pgrep -f ovs-vswitchd.*s1) -n \ tc qdisc add dev s1-eth1 root netem loss 5% delay 50ms 10ms distribution normal # 解释5% 丢包率 50ms 基础延迟 ±10ms 抖动正态分布丢包验证技巧ping丢包率不可靠ICMP 优先级高常被 bypass正确方法h1 ping -c 20 h2后执行sudo tc -s qdisc show dev s1-eth1查看drops字段计数更准用iperf3 -c h2 -u -b 10M -t 10UDP 模式iperf3客户端会显示Packet Loss百分比。4.3 对比 FIFO 与 SFQ 队列对 TCP 公平性的影响课设常要求“证明 SFQ 比 FIFO 更公平”。需同时启动两个 TCP 流观察吞吐量分配# 启动两个 iperf3 服务端h2/h3 h2 iperf3 -s -D h3 iperf3 -s -D # 在 h1 上同时发起两个流注意-P 2 会创建 2 个并行流非公平对比 h1 iperf3 -c h2 -t 30 -i 2 h1 iperf3 -c h3 -t 30 -i 2 # 但真正的公平性测试需用不同端口、不同 cwnd 初始值 # 更佳方案用 Python socket 控制发送节奏SFQ 部署命令# 替换 s1-eth1 的 qdisc 为 SFQ sudo nsenter -t $(pgrep -f ovs-vswitchd.*s1) -n \ tc qdisc replace dev s1-eth1 root sfq perturb 10 # perturb 10每 10 秒重新哈希流避免长连接独占队列观测公平性的黄金指标tc -s class show dev s1-eth1查看每个 flow 的sent字节数SFQ 下应接近 1:1ss -i在 h1 上查看两个连接的cwnd、ssthreshFIFO 下一个流可能 cwnd100另一个 stuck at 10tcpdump -i any port 5201 -w fifo.pcap抓包后用 Wireshark 的Statistics → TCP Stream Graph → Window Scaling查看窗口变化曲线。玄学提醒tc qdisc add ... sfq后tc -s qdisc可能显示0 flows这是正常现象——SFQ 动态创建 flow需有实际流量触发。务必先h1 ping h2一次再查。5. 避坑指南课设中最常翻车的 5 个场景附现象、根因与一招止血命令Mininet 课设的报错往往藏在日志深处表面是ping fail实则是 namespace、内核模块、OpenFlow 版本三重绞杀。以下是学生提交报告前 2 小时最高频的 5 类翻车现场每条都来自真实 debug 截图。5.1 现象mn --topo single,3启动后s1状态为is_connected: falseovs-ofctl show s1显示s1-eth1: disconnected原因Open vSwitch 内核模块未加载或ovs-vswitchd进程崩溃。is_connected: false表示交换机未与控制器建立 OpenFlow 连接但根源常在底层数据平面。解决# 1. 强制重启 ovs 服务 sudo service openvswitch-switch restart # 2. 检查 ovs-vswitchd 是否存活 sudo ps aux | grep ovs-vswitchd # 3. 若进程不存在手动启动并查看日志 sudo ovs-vswitchd --pidfile --detach sudo journalctl -u openvswitch-switch -n 50 --no-pager # 查找 could not initialize datapath 或 failed to open /dev/openvswitch血泪经验journalctl日志中若出现openvswitch: module verification failed: signature and/or required key missing说明内核模块签名失败——此时必须sudo modprobe -r openvswitch sudo modprobe openvswitch重载而非重启服务。5.2 现象h1 ping h2通但h1 curl http://h2超时tcpdump -i h1-eth0 port 80无任何包原因h2 未监听 80 端口或防火墙iptables拦截。ping通只证明 ICMP 层通HTTP 需 TCP 三次握手 应用层服务。解决# 在 h2 上检查端口监听 h2 ss -tlnp | grep :80 # 若无输出启动简易 HTTP 服务 h2 python3 -m http.server 80 # 检查 h2 的 iptables默认 ACCEPT但课设脚本可能误配 h2 iptables -L INPUT -v | grep dpt:80 # 若有 DROP 规则清空h2 iptables -F INPUT5.3 现象ovs-ofctl dump-flows s1返回空但ovs-ofctl show s1显示端口 up原因控制器未下发流表或控制器地址错误。dump-flows查的是 OpenFlow 流表空表示控制器未推送任何规则此时交换机处于“无脑泛洪”模式仅对已知 MAC 转发。解决# 1. 确认控制器进程在运行如 Ryu ryu-manager --verbose ryu.app.simple_switch_13 # 2. 检查 Mininet 启动时控制器 IP 是否匹配 sudo mn --controller remote,ip127.0.0.1,port6633 # 必须与 ryu 监听地址一致 # 3. 在 Ryu 日志中搜索 connected 确认 s1 已注册 tail -f /tmp/ryu.log | grep connected5.4 现象tc qdisc add dev s1-eth1 root netem delay 100ms执行后ping延迟无变化原因tc命令在 host namespace 执行但s1-eth1属于s1的 network namespacehost 下的tc对其无效。解决# 正确做法进入 s1 的 namespace 执行 sudo nsenter -t $(pgrep -f ovs-vswitchd.*s1) -n \ tc qdisc add dev s1-eth1 root netem delay 100ms # 验证在 s1 namespace 中查看 sudo nsenter -t $(pgrep -f ovs-vswitchd.*s1) -n \ tc qdisc show dev s1-eth15.5 现象h1 iperf3 -c h2 -t 30吞吐量远低于预期如设限 10M 却只跑 2M原因TCP 拥塞窗口未打开常因tc的burst设置过小或iperf3客户端缓冲区不足。解决# 1. 增大 tc burst至少 64kbit sudo nsenter -t $(pgrep -f ovs-vswitchd.*s1) -n \ tc qdisc replace dev s1-eth1 root tbf rate 10mbit burst 64kbit latency 100ms # 2. 增大 iperf3 缓冲区-w 256K h1 iperf3 -c h2 -t 30 -w 256K # 3. 强制 TCP 使用 cubic避免部分内核默认 bbr 导致异常 h1 sysctl -w net.ipv4.tcp_congestion_controlcubic注意iperf3 -w参数单位是字节256K 256*1024 字节。过小的缓冲区如默认 8K会导致 TCP 窗口无法填满吞吐量被锁死。6. 实验报告提效技巧用 scapy 自动生成拓扑图 用 pandas 统计流表命中率告别手绘与 Excel课设报告的“实验结果分析”章节90% 的学生还在用 Visio 画拓扑、用 Wireshark 手动数包、用计算器算丢包率。其实 Mininet 提供了完整的 API 接口配合scapy和pandas可 5 行代码生成 SVG 拓扑图、10 行代码导出流表统计 CSV——这才是工程师该有的效率。6.1 用 scapy 自动生成拓扑 SVG 图无需 GUIMininet 的net.topo对象包含所有节点和链路信息可直接导出为 Graphviz DOT 格式再用scapy的graphviz模块渲染#!/usr/bin/env python3 gen_topo_svg.py从 Mininet net 对象生成拓扑 SVG - 输入已启动的 Mininet net 实例 - 输出topo.svg含交换机/主机/链路标签 from mininet.net import Mininet from mininet.topo import SingleSwitchTopo import os def gen_topo_svg(net, filenametopo.svg): # 构建 DOT 字符串 dot digraph G {\n rankdirLR;\n # 添加节点 for node in net.nodes(): if s in node.name: # 交换机 dot f {node.name} [shapebox, stylefilled, fillcolorlightblue];\n else: # 主机 dot f {node.name} [shapeellipse, stylefilled, fillcolorlightgreen];\n # 添加链路仅物理链路不含控制器链路 for link in net.links(): if c0 not in str(link): # 过滤控制器链路 src, dst link.intf1.node.name, link.intf2.node.name dot f {src} - {dst} [label{link.intf1.name}-{link.intf2.name}];\n dot } # 写入 DOT 文件并调用 graphviz 渲染 with open(topo.dot, w) as f: f.write(dot) os.system(dot -Tsvg topo.dot -o {}.format(filename)) print(fTopology SVG saved to {filename}) # 使用示例在 Mininet CLI 中执行 # from gen_topo_svg import gen_topo_svg # gen_topo_svg(net)依赖安装sudo apt install graphviz -y pip3 install pygraphviz # 注意需先装 graphviz 再 pip生成的topo.svg可直接插入 Word 报告比手绘准确 10 倍且每次拓扑变更自动更新。6.2 用 pandas 分析流表命中率量化控制器性能课设常要求“分析流表匹配效率”但ovs-ofctl dump-flows s1输出是文本手动统计packets:字本文还有配套的精品资源点击获取