不同网络布局比较

不同网络布局比较:使用networkx库创建一个环形网络拓扑和一个树形网络拓扑,模拟数据在这两种拓扑结构中的传输。设置不同的网络参数(如链路带宽、节点处理能力等),比较它们的数据传输效率(如平均传输时间、吞吐量等)和可靠性(如链路故障时的数据传输情况),并给出相应的分析报告。

import networkx as nx
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import random
import time
from typing import List, Dict, Tuple
import matplotlib.animation as animation
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import tkinter as tk
from tkinter import ttk, scrolledtext
from matplotlib.figure import Figure
# 设置matplotlib中文字体
plt.rcParams["font.family"] = ["SimHei", "WenQuanYi Micro Hei", "Heiti TC"]
plt.rcParams["axes.unicode_minus"] = False  # 解决负号显示问题


class NetworkTopology:
    """网络拓扑基类"""

    def __init__(self, num_nodes: int, name: str):
        self.num_nodes = num_nodes
        self.name = name
        self.G = nx.Graph()
        self.node_status = {i: True for i in range(num_nodes)}  # 节点状态
        self.link_status = {}  # 链路状态
        self.node_processing_capacity = {}  # 节点处理能力
        self.link_bandwidth = {}  # 链路带宽
        self.transmission_history = []  # 传输历史
        self.current_transmission = None  # 当前传输

        # 初始化节点和链路属性
        self._initialize_nodes()
        self._initialize_links()

        # 为节点设置固定位置,确保动画中节点不会移动
        self.pos = self._get_node_positions()

    def _initialize_nodes(self):
        """初始化节点属性"""
        for i in range(self.num_nodes):
            self.G.add_node(i)
            # 随机节点处理能力 (1-10)
            self.node_processing_capacity[i] = random.randint(1, 10)

    def _initialize_links(self):
        """初始化链路属性,由子类实现"""
        pass

    def _get_node_positions(self):
        """获取节点位置,由子类实现"""
        pass

    def simulate_transmission(self, source: int, destination: int, data_size: int) -> Dict:
        """模拟从源节点到目标节点的数据传输"""
        if not self.node_status[source] or not self.node_status[destination]:
            result = {
                "success": False,
                "transmission_time": float('inf'),
                "route": [],
                "message": "源节点或目标节点故障"
            }
            self.transmission_history.append(result)
            return result

        # 查找路径
        try:
            # 使用Dijkstra算法查找最短路径
            route = nx.shortest_path(self.G, source, destination)
        except nx.NetworkXNoPath:
            result = {
                "success": False,
                "transmission_time": float('inf'),
                "route": [],
                "message": "无可用路径"
            }
            self.transmission_history.append(result)
            return result

        # 检查路径上的所有节点和链路是否正常
        for i in range(len(route) - 1):
            u, v = route[i], route[i + 1]
            if not self.node_status[u] or not self.node_status[v]:
                result = {
                    "success": False,
                    "transmission_time": float('inf'),
                    "route": route,
                    "message": f"路径上节点 {u} 或 {v} 故障"
                }
                self.transmission_history.append(result)
                return result

            # 检查链路状态,使用元组的排序版本作为键
            link = (u, v) if u < v else (v, u)
            if not self.link_status.get(link, True):
                result = {
                    "success": False,
                    "transmission_time": float('inf'),
                    "route": route,
                    "message": f"链路 {u}-{v} 故障"
                }
                self.transmission_history.append(result)
                return result

        # 计算传输时间
        transmission_time = self._calculate_transmission_time(route, data_size)

        # 模拟随机传输失败(例如,5%的概率失败)
        success = random.random() > 0.05

        result = {
            "success": success,
            "transmission_time": transmission_time if success else float('inf'),
            "route": route,
            "message": "传输成功" if success else "随机传输失败"
        }

        self.current_transmission = (source, destination, success, route)
        self.transmission_history.append(result)

        return result

    def _calculate_transmission_time(self, route: List[int], data_size: int) -> float:
        """计算传输时间"""
        # 传输时间 = 处理延迟 + 传播延迟 + 排队延迟

        processing_delay = 0
        propagation_delay = 0
        queuing_delay = 0

        # 计算处理延迟
        for node in route:
            # 处理延迟 = 数据大小 / 节点处理能力
            processing_delay += data_size / self.node_processing_capacity[node]

        # 计算传播延迟和排队延迟
        for i in range(len(route) - 1):
            u, v = route[i], route[i + 1]
            link = (u, v) if u < v else (v, u)

            # 传播延迟 = 数据大小 / 链路带宽
            propagation_delay += data_size / self.link_bandwidth[link]

            # 简单模拟排队延迟 (随机值)
            queuing_delay += random.uniform(0, 0.1 * data_size)

        total_time = processing_delay + propagation_delay + queuing_delay
        return total_time

    def analyze_reliability(self, simulation_rounds: int = 1000) -> Dict:
        """分析网络可靠性"""
        # 基础可靠性 - 所有节点和链路正常
        base_success_rate = self._run_reliability_test(simulation_rounds)

        # 模拟随机链路故障
        links = list(self.link_status.keys())
        if links:
            random_link = random.choice(links)
            original_status = self.link_status.get(random_link, True)
            self.link_status[random_link] = False
            link_failure_rate = self._run_reliability_test(simulation_rounds)
            self.link_status[random_link] = original_status  # 恢复链路状态
        else:
            link_failure_rate = 0

        # 模拟随机节点故障
        if self.num_nodes > 0:
            random_node = random.choice(list(range(self.num_nodes)))
            original_status = self.node_status[random_node]
            self.node_status[random_node] = False
            node_failure_rate = self._run_reliability_test(simulation_rounds)
            self.node_status[random_node] = original_status  # 恢复节点状态
        else:
            node_failure_rate = 0

        return {
            "base_success_rate": base_success_rate,
            "link_failure_impact": base_success_rate - link_failure_rate,
            "node_failure_impact": base_success_rate - node_failure_rate
        }

    def _run_reliability_test(self, rounds: int) -> float:
        """运行可靠性测试,返回成功率"""
        successes = 0
        for _ in range(rounds):
            # 随机选择源和目标节点
            available_nodes = [i for i in self.node_status if self.node_status[i]]
            if len(available_nodes) < 2:
                continue

            source, destination = random.sample(available_nodes, 2)
            result = self.simulate_transmission(source, destination, 100)
            if result["success"]:
                successes += 1

        return successes / rounds if rounds > 0 else 0

    def get_performance_metrics(self) -> Dict:
        """获取性能指标"""
        successful_transmissions = [t for t in self.transmission_history if t["success"]]

        if not successful_transmissions:
            return {
                "average_transmission_time": float('nan'),
                "throughput": 0,
                "success_rate": 0
            }

        # 计算平均传输时间
        avg_transmission_time = sum(t["transmission_time"] for t in successful_transmissions) / len(
            successful_transmissions)

        # 计算吞吐量 (成功传输的数据总量 / 总传输时间)
        total_data = sum(100 for _ in successful_transmissions)  # 假设每次传输100单位数据
        total_time = sum(t["transmission_time"] for t in successful_transmissions)
        throughput = total_data / total_time if total_time > 0 else 0

        # 计算成功率
        success_rate = len(successful_transmissions) / len(
            self.transmission_history) if self.transmission_history else 0

        return {
            "average_transmission_time": avg_transmission_time,
            "throughput": throughput,
            "success_rate": success_rate
        }

    def draw_network(self, ax):
        """绘制网络拓扑图"""
        ax.clear()

        # 获取节点颜色(绿色表示正常,红色表示故障)
        node_colors = ['#10b981' if self.node_status[i] else '#ef4444' for i in self.G.nodes]

        # 节点大小
        node_sizes = [300 for _ in self.G.nodes]

        # 绘制节点和边
        nx.draw_networkx_nodes(self.G, self.pos, ax=ax, node_color=node_colors, node_size=node_sizes)

        # 获取边的颜色(灰色表示正常,红色表示故障)
        edge_colors = []
        edge_widths = []
        for u, v in self.G.edges:
            link = (u, v) if u < v else (v, u)
            if not self.link_status.get(link, True):
                edge_colors.append('#ef4444')
                edge_widths.append(2.0)
            else:
                edge_colors.append('#64748b')
                edge_widths.append(1.5)

        nx.draw_networkx_edges(self.G, self.pos, ax=ax, edge_color=edge_colors, width=edge_widths)
        nx.draw_networkx_labels(self.G, self.pos, ax=ax, font_family="SimHei")

        # 如果有当前传输,高亮显示
        if self.current_transmission:
            source, destination, success, route = self.current_transmission
            edge_color = '#10b981' if success else '#ef4444'

            # 高亮路径
            for i in range(len(route) - 1):
                u, v = route[i], route[i + 1]
                ax.plot(
                    [self.pos[u][0], self.pos[v][0]],
                    [self.pos[u][1], self.pos[v][1]],
                    color=edge_color, linewidth=3, alpha=0.7
                )

            # 高亮源节点和目标节点
            ax.plot(
                self.pos[source][0], self.pos[source][1],
                'o', color='#f59e0b', markersize=12, alpha=0.7
            )
            ax.plot(
                self.pos[destination][0], self.pos[destination][1],
                'o', color='#f59e0b', markersize=12, alpha=0.7
            )

        ax.set_title(f"{self.name} 拓扑结构")
        ax.axis('off')


class RingTopology(NetworkTopology):
    """环形网络拓扑"""

    def __init__(self, num_nodes: int):
        super().__init__(num_nodes, "环形")

    def _initialize_links(self):
        """初始化链路"""
        for i in range(self.num_nodes):
            # 每个节点连接到下一个节点,形成环
            j = (i + 1) % self.num_nodes
            self.G.add_edge(i, j)
            # 随机链路带宽 (5-20)
            self.link_bandwidth[(i, j)] = random.randint(5, 20)
            self.link_bandwidth[(j, i)] = self.link_bandwidth[(i, j)]  # 双向链路
            self.link_status[(i, j)] = True
            self.link_status[(j, i)] = True

    def _get_node_positions(self):
        """获取节点位置(环形布局)"""
        return nx.circular_layout(self.G)


class TreeTopology(NetworkTopology):
    """树形网络拓扑"""

    def __init__(self, num_nodes: int):
        # 计算树的分支因子,使得树尽可能平衡
        self.branching_factor = 2
        while self.branching_factor ** 2 - 1 < num_nodes:
            self.branching_factor += 1

        super().__init__(num_nodes, "树形")

    def _initialize_links(self):
        """初始化链路"""
        # 创建一个平衡树
        for i in range(1, self.num_nodes):
            parent = (i - 1) // self.branching_factor
            self.G.add_edge(parent, i)
            # 随机链路带宽 (5-20)
            self.link_bandwidth[(parent, i)] = random.randint(5, 20)
            self.link_bandwidth[(i, parent)] = self.link_bandwidth[(parent, i)]  # 双向链路
            self.link_status[(parent, i)] = True
            self.link_status[(i, parent)] = True

    def _get_node_positions(self):
        """获取节点位置(树形布局)"""
        return nx.spring_layout(self.G, seed=42)


class NetworkComparisonGUI:
    """网络比较图形界面"""

    def __init__(self, root, num_nodes=10):
        self.root = root
        self.root.title("不同网络拓扑结构比较分析")
        self.root.geometry("1200x800")
        self.root.configure(bg="#f5f5f5")

        self.num_nodes = num_nodes
        self.is_running = False
        self.simulation_speed = 1000  # 毫秒
        self.rounds = 0

        self.ring_topology = RingTopology(num_nodes)
        self.tree_topology = TreeTopology(num_nodes)

        self.create_widgets()
        self.update_statistics()

    def create_widgets(self):
        """创建GUI组件"""
        # 主框架
        main_frame = ttk.Frame(self.root, padding="10")
        main_frame.pack(fill=tk.BOTH, expand=True)

        # 控制按钮框架
        control_frame = ttk.Frame(main_frame)
        control_frame.pack(fill=tk.X, pady=(0, 10))

        self.start_button = ttk.Button(control_frame, text="开始模拟", command=self.start_simulation)
        self.start_button.pack(side=tk.LEFT, padx=(0, 10))

        self.pause_button = ttk.Button(control_frame, text="暂停", command=self.pause_simulation, state=tk.DISABLED)
        self.pause_button.pack(side=tk.LEFT, padx=(0, 10))

        self.reset_button = ttk.Button(control_frame, text="重置", command=self.reset_simulation)
        self.reset_button.pack(side=tk.LEFT)

        # 网络拓扑图框架
        topologies_frame = ttk.Frame(main_frame)
        topologies_frame.pack(fill=tk.BOTH, expand=True)

        # 环形网络框架
        ring_frame = ttk.LabelFrame(topologies_frame, text="环形网络", padding="10")
        ring_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=(0, 10))

        # 树形网络框架
        tree_frame = ttk.LabelFrame(topologies_frame, text="树形网络", padding="10")
        tree_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True)

        # 创建Matplotlib图形
        self.ring_fig = Figure(figsize=(5, 4), dpi=100)
        self.ring_ax = self.ring_fig.add_subplot(111)
        self.ring_canvas = FigureCanvasTkAgg(self.ring_fig, master=ring_frame)
        self.ring_canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True)

        self.tree_fig = Figure(figsize=(5, 4), dpi=100)
        self.tree_ax = self.tree_fig.add_subplot(111)
        self.tree_canvas = FigureCanvasTkAgg(self.tree_fig, master=tree_frame)
        self.tree_canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True)

        # 统计数据框架
        stats_frame = ttk.LabelFrame(main_frame, text="性能比较", padding="10")
        stats_frame.pack(fill=tk.BOTH, expand=True, pady=(10, 0))

        # 创建统计数据表格
        columns = ("指标", "环形网络", "树形网络")
        self.stats_tree = ttk.Treeview(stats_frame, columns=columns, show="headings")

        for col in columns:
            self.stats_tree.heading(col, text=col)
            self.stats_tree.column(col, width=200, anchor=tk.CENTER)

        self.stats_tree.pack(fill=tk.BOTH, expand=True)

        # 初始化表格数据
        self.stats_items = []
        for metric in ["平均传输时间", "吞吐量", "成功率", "基础可靠性", "链路故障影响", "节点故障影响"]:
            item = self.stats_tree.insert("", tk.END, values=(metric, "--", "--"))
            self.stats_items.append(item)

        # 绘制初始网络拓扑图
        self.draw_networks()

    def draw_networks(self):
        """绘制网络拓扑图"""
        self.ring_topology.draw_network(self.ring_ax)
        self.tree_topology.draw_network(self.tree_ax)
        self.ring_canvas.draw()
        self.tree_canvas.draw()

    def simulate_step(self):
        """模拟一步数据传输"""
        if not self.is_running:
            return

        # 为环形网络模拟一次传输
        available_nodes = [i for i in self.ring_topology.node_status if self.ring_topology.node_status[i]]
        if len(available_nodes) >= 2:
            source, destination = random.sample(available_nodes, 2)
            data_size = random.randint(50, 200)
            self.ring_topology.simulate_transmission(source, destination, data_size)

        # 为树形网络模拟一次传输
        available_nodes = [i for i in self.tree_topology.node_status if self.tree_topology.node_status[i]]
        if len(available_nodes) >= 2:
            source, destination = random.sample(available_nodes, 2)
            data_size = random.randint(50, 200)
            self.tree_topology.simulate_transmission(source, destination, data_size)

        self.rounds += 1

        # 每10轮分析一次可靠性
        if self.rounds % 10 == 0:
            self.update_statistics()

        # 更新图形
        self.draw_networks()

        # 安排下一步模拟
        self.root.after(self.simulation_speed, self.simulate_step)

    def update_statistics(self):
        """更新统计数据"""
        # 获取性能指标
        ring_metrics = self.ring_topology.get_performance_metrics()
        tree_metrics = self.tree_topology.get_performance_metrics()

        # 分析可靠性
        ring_reliability = self.ring_topology.analyze_reliability(100)
        tree_reliability = self.tree_topology.analyze_reliability(100)

        # 更新表格数据
        values = [
            (
            f"{ring_metrics['average_transmission_time']:.2f}秒", f"{tree_metrics['average_transmission_time']:.2f}秒"),
            (f"{ring_metrics['throughput']:.2f}单位/秒", f"{tree_metrics['throughput']:.2f}单位/秒"),
            (f"{ring_metrics['success_rate']:.2%}", f"{tree_metrics['success_rate']:.2%}"),
            (f"{ring_reliability['base_success_rate']:.2%}", f"{tree_reliability['base_success_rate']:.2%}"),
            (f"{ring_reliability['link_failure_impact']:.2%}", f"{tree_reliability['link_failure_impact']:.2%}"),
            (f"{ring_reliability['node_failure_impact']:.2%}", f"{tree_reliability['node_failure_impact']:.2%}")
        ]

        for i, (ring_val, tree_val) in enumerate(values):
            self.stats_tree.item(self.stats_items[i],
                                 values=(self.stats_tree.item(self.stats_items[i])['values'][0], ring_val, tree_val))

    def start_simulation(self):
        """开始模拟"""
        if not self.is_running:
            self.is_running = True
            self.start_button.config(state=tk.DISABLED)
            self.pause_button.config(state=tk.NORMAL)
            self.simulate_step()

    def pause_simulation(self):
        """暂停模拟"""
        if self.is_running:
            self.is_running = False
            self.start_button.config(state=tk.NORMAL)
            self.pause_button.config(state=tk.DISABLED)

    def reset_simulation(self):
        """重置模拟"""
        self.pause_simulation()
        self.rounds = 0
        self.ring_topology = RingTopology(self.num_nodes)
        self.tree_topology = TreeTopology(self.num_nodes)
        self.draw_networks()
        self.update_statistics()


def generate_analysis_report(ring_topology, tree_topology, simulation_rounds=1000):
    """生成分析报告"""
    print("\n" + "=" * 50)
    print("不同网络拓扑结构比较分析报告")
    print("=" * 50)

    # 1. 网络拓扑概述
    print("\n一、网络拓扑概述")
    print(f"1. 环形网络: {ring_topology.num_nodes}个节点,形成环形连接")
    print(f"2. 树形网络: {tree_topology.num_nodes}个节点,形成树形层次结构")

    # 2. 性能指标比较
    print("\n二、性能指标比较")

    # 运行多次模拟获取更准确的结果
    for _ in range(simulation_rounds):
        # 环形网络模拟
        available_nodes = [i for i in ring_topology.node_status if ring_topology.node_status[i]]
        if len(available_nodes) >= 2:
            source, destination = random.sample(available_nodes, 2)
            ring_topology.simulate_transmission(source, destination, 100)

        # 树形网络模拟
        available_nodes = [i for i in tree_topology.node_status if tree_topology.node_status[i]]
        if len(available_nodes) >= 2:
            source, destination = random.sample(available_nodes, 2)
            tree_topology.simulate_transmission(source, destination, 100)

    # 获取性能指标
    ring_metrics = ring_topology.get_performance_metrics()
    tree_metrics = tree_topology.get_performance_metrics()

    # 打印性能指标
    print("\n1. 平均传输时间")
    print(f"   环形网络: {ring_metrics['average_transmission_time']:.2f}秒")
    print(f"   树形网络: {tree_metrics['average_transmission_time']:.2f}秒")

    print("\n2. 吞吐量")
    print(f"   环形网络: {ring_metrics['throughput']:.2f}单位/秒")
    print(f"   树形网络: {tree_metrics['throughput']:.2f}单位/秒")

    print("\n3. 成功率")
    print(f"   环形网络: {ring_metrics['success_rate']:.2%}")
    print(f"   树形网络: {tree_metrics['success_rate']:.2%}")

    # 3. 可靠性分析
    print("\n三、可靠性分析")

    # 分析可靠性
    ring_reliability = ring_topology.analyze_reliability(1000)
    tree_reliability = tree_topology.analyze_reliability(1000)

    print("\n1. 基础可靠性 (无故障情况下的成功率)")
    print(f"   环形网络: {ring_reliability['base_success_rate']:.2%}")
    print(f"   树形网络: {tree_reliability['base_success_rate']:.2%}")

    print("\n2. 链路故障影响 (随机一条链路故障导致的成功率下降)")
    print(f"   环形网络: {ring_reliability['link_failure_impact']:.2%}")
    print(f"   树形网络: {tree_reliability['link_failure_impact']:.2%}")

    print("\n3. 节点故障影响 (随机一个节点故障导致的成功率下降)")
    print(f"   环形网络: {ring_reliability['node_failure_impact']:.2%}")
    print(f"   树形网络: {tree_reliability['node_failure_impact']:.2%}")

    # 4. 综合分析
    print("\n四、综合分析")

    # 性能分析
    print("\n1. 性能方面:")
    if ring_metrics['average_transmission_time'] < tree_metrics['average_transmission_time']:
        print("   - 环形网络平均传输时间更短,数据传输更快")
    else:
        print("   - 树形网络平均传输时间更短,数据传输更快")

    if ring_metrics['throughput'] > tree_metrics['throughput']:
        print("   - 环形网络吞吐量更高,更适合高流量场景")
    else:
        print("   - 树形网络吞吐量更高,更适合高流量场景")

    if ring_metrics['success_rate'] > tree_metrics['success_rate']:
        print("   - 环形网络成功率更高,传输更可靠")
    else:
        print("   - 树形网络成功率更高,传输更可靠")

    # 可靠性分析
    print("\n2. 可靠性方面:")
    if ring_reliability['link_failure_impact'] < tree_reliability['link_failure_impact']:
        print("   - 环形网络对链路故障更具弹性")
    else:
        print("   - 树形网络对链路故障更具弹性")

    if ring_reliability['node_failure_impact'] < tree_reliability['node_failure_impact']:
        print("   - 环形网络对节点故障更具弹性")
    else:
        print("   - 树形网络对节点故障更具弹性")

    # 5. 适用场景建议
    print("\n五、适用场景建议")
    print("1. 环形网络:")
    print("   - 适合需要均匀分布流量的场景")
    print("   - 对链路故障有较好的容错能力")
    print("   - 适合规模较小的网络")

    print("\n2. 树形网络:")
    print("   - 适合分层管理的场景")
    print("   - 对中心节点依赖性较强,需确保根节点可靠性")
    print("   - 适合扩展性要求较高的网络")


if __name__ == "__main__":
    # 生成分析报告
    num_nodes = 10
    ring = RingTopology(num_nodes)
    tree = TreeTopology(num_nodes)
    generate_analysis_report(ring, tree)

    # 启动GUI
    root = tk.Tk()
    app = NetworkComparisonGUI(root, num_nodes)
    root.mainloop()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值