模拟实现路由器

模拟路由器

概述

在本项目中将编写一个简单模拟路由器。该路由器将接收原始以太网帧,并像真正的路由器一样处理它们:将它们转发到正确的传出接口,创建新帧等。 本项目中,可以将路由器、主机节点、交换机节点以线程或进程的方式实现,节点之间的通信看成是线程/进程间通信,使用进程间通信机制或消息队列等其它方式实现。

路由器任务描述

  • 处理以太网帧
  • 处理ARP分组
  • 处理IPV4分组
  • 处理ICMP分组

主机节点任务描述

  • 构造IPV4分组
  • 构造以太网帧

交换机任务描述

  • 交换表数据结构
  • 实现以太网交换机自学习算法
  • 基于以太网转发以太网帧
  • 处理多个以太网交换机组网的情形

路由器路由算法任务描述

  • 设计基于链路状态的路由通告报文
  • 实现路由泛洪算法在路由器间交换报文
  • 基于最短路径算法构建路由表
  • 使用构建的路由表转发分组
  • 模拟链路失效,出发路由更新,观测路由震荡

最终实现目标

目前代码还未完全实现,逐步更新中…

import heapq
import threading
import time
import queue


# 根据子网掩码和目的网络地址得到目的网络号
def bitwise_and_binary_to_decimal(bin_str1, bin_str2):
    # 将二进制字符串转换为整数,进行按位与操作
    result_int = int(bin_str1, 2) & int(bin_str2, 2)

    # 将整数转换为点分十进制形式
    result_decimal = ".".join(map(str, [(result_int >> (24 - i*8)) & 255 for i in range(4)]))

    return result_decimal


# 获取子网掩码
def get_mask_by_number(router_ports, port_number):
    for port in router_ports:
        if port.port == port_number:
            return port.mask
    return None


# 获取mac列表
def get_keys_except_value(dictionary, value_to_exclude):
    keys_except_value = [key for key, value in dictionary.items() if value != value_to_exclude]
    return keys_except_value


# 二进制字符串转点分十进制
def binary_to_ipv4(binary_address):
    binary_parts = binary_address.split('.')
    decimal_parts = [str(int(part, 2)) for part in binary_parts]
    ipv4_address = '.'.join(decimal_parts)
    return ipv4_address


# 二进制int转点分十进制
def int_to_ipv4(decimal_int):
    # 将32位整数转换为点分十进制形式
    ip_parts = [(decimal_int >> (24 - i*8)) & 255 for i in range(4)]
    decimal_ip = ".".join(map(str, ip_parts))
    return decimal_ip


# 点分十进制转二进制
def ipv4_to_binary(ipv4_address):
    binary_parts = [bin(int(part))[2:].zfill(8) for part in ipv4_address.split('.')]
    binary_address = ''.join(binary_parts)
    return binary_address


def binary_to_decimal_ipv4(binary_ip):
    # 将二进制字符串分割成四个八位组
    octets = [binary_ip[i:i+8] for i in range(0, len(binary_ip), 8)]

    # 将每个八位组转换为十进制
    decimal_values = [int(octet, 2) for octet in octets]

    # 将十进制值连接成点分十进制形式
    decimal_ip = ".".join(map(str, decimal_values))

    return decimal_ip


# 以太网帧
class EthernetFrame:
    def __init__(self, dec_mac, s_mac, type, data):
        super().__init__()
        # Ethernet ||数据帧首部 14Bytes
        self.d_mac = dec_mac  # 6Bytes
        self.s_mac = s_mac  # 6Bytes
        self.type = type  # 2Bytes
        # 上层数据,已封装
        self.data = data


# IPV4报文
class IPV4:
    def __init__(self, tos, s_ip, d_ip, data):
        super(IPV4, self).__init__()
        # IPV4首部 20Bytes+
        self.version = 0x4  # 4b 版本号 ipv4是0100
        self.IHL = 0x5  # 4b 头部长度
        self.Tos = tos  # 8b 服务类型
        self.Total_length = 0x0033  # 16b 总长度
        self.id_num = 0x285b  # 16b id号
        self.Flags = 0b010  # 3b 标志
        self.fragment = 0b0000000000000  # 13b 分片偏移量
        self.TTL = 0b01000000  # 8b 生存时间
        self.protocol = 0b00010001  # 8b 协议号
        self.HeaderCheckSum = 0x0000  # 头部校验和
        self.s_ip = s_ip  # 32b 发送方ip
        self.d_ip = d_ip  # 32b 接收方ip
        # 上一层的数据报
        self.data = data


# ICMP报文
class ICMP:
    def __init__(self, type, code, data):
        super().__init__()
        self.type = type  # 1Byte 类型
        self.code = code  # 1Byte 代码
        self.checksum = 0x00  # 2Bytes 校验和
        self.content = 0x0000  # 8Bytes 内容
        # 上层数据报
        self.data = data

    def initICMP(self, icmpType, code, data):
        print('正在生成ICMP数据报')
        self.type = icmpType
        self.code = code
        self.data = data

        print('ICMP数据报已生成')


# ARP报文
class ARP:
    def __init__(self, operation_type, s_mac, s_ip, d_mac, d_ip):
        super().__init__()
        self.type = 0x01  # 2Bytes 硬件类型 以太网地址为1
        self.protocol = 0x0800  # 2Bytes 上层协议类型  IP为0x0800
        self.MacLength = 0x6  # 1Byte 标识MAC地址长度
        self.IPLength = 0x4  # 1Byte
        self.OperType = operation_type  # 2 Bytes操作类型 1为ARP请求,2为ARP应答
        self.s_mac = s_mac
        self.s_ip = s_ip
        self.d_ip = d_ip
        self.d_mac = d_mac


class RouterPort:
    def __init__(self, port, ip_address, mask):
        self.port = port
        self.ip_address = ip_address
        self.mask = mask


# 路由表项
class RouterTableEmit:
    def __init__(self, net_num, mask, nextHop, port):
        self.net_num = net_num
        self.mask = mask
        self.nextHop = nextHop
        self.port = port


# 路由器
class Router(threading.Thread):
    def __init__(self, mac_address, ip_address, forward_table, Router_port, frame_queue, router_table):
        super().__init__()
        self.mac_address = mac_address
        self.ip_address = ip_address
        self.router_port = Router_port
        self.router_table = router_table
        self.arp_table = {}
        self.connected_port = None
        self.link_state_database = {}
        self.frame_queue = frame_queue  # 报文队列用于缓存所有接收到的数据帧
        self.forward_queue = forward_table  # 交换机提取报文所需队列

    def print_router_table(self):
        print("这里是路由表")
        for entry in self.router_table:
            print(f"Net_num: {entry.net_num}, Mask: {entry.mask}, NextHop: {entry.nextHop}, Port: {entry.port}")

    def print_queue(self):
        # 获取字典中的每一个键和值
        for key, value in self.frame_queue.items():
            print(f"Key: {key}, Value: {value}")

    def connect_to_switch(self):
        with self.lock:
            self.connected_port = self.switch.get_switch_port(self.connected_port)

    # 查询路由表
    def query_router_table(self):
        pass

    # 添加ARP表
    def add_arp(self, arp_ip, arp_mac):  # 添加arp表记录
        self.arp_table[arp_ip] = arp_mac

    # 构建路径
    def construct_path(self, destination_router_id, predecessors):
        path = []
        current_router_id = destination_router_id
        while current_router_id is not None:
            path.insert(0, current_router_id)
            current_router_id = predecessors[current_router_id]
        return path

    # 计算最短路径
    def calculate_shortest_paths(self):  # 计算最短路径
        # 初始化距离和前驱节点
        distances = {router_id: float("inf") for router_id in self.link_state_database}
        distances[self.router_id] = 0
        predecessors = {router_id: None for router_id in self.link_state_database}

        # 使用Dijkstra算法计算最短路径
        queue = [(0, self.router_id)]  # 优先队列,用于选择下一个要处理的节点
        while queue:
            curr_distance, curr_router = heapq.heappop(queue)
            if curr_distance > distances[curr_router]:
                continue

            # 遍历当前节点的邻居
            if curr_router in self.link_state_database:
                for neighbor_router, cost in self.link_state_database[curr_router].items():
                    new_distance = curr_distance + cost
                    if new_distance < distances[neighbor_router]:
                        distances[neighbor_router] = new_distance
                        predecessors[neighbor_router] = curr_router
                        heapq.heappush(queue, (new_distance, neighbor_router))

        # 构建最短路径字典
        shortest_paths = {}
        for destination_router_id in self.link_state_database:
            path = self.construct_path(destination_router_id, predecessors)
            shortest_paths[destination_router_id] = path

        return shortest_paths

    # 构建路由表
    def build_routing_table(self):  # 完善路由表
        # 使用Dijkstra算法计算最短路径
        shortest_paths = self.calculate_shortest_paths()

        # 构建路由表
        for destination_router_id, path in shortest_paths.items():
            if len(path) >= 2:
                next_hop = path[1]  # 下一跳路由器
                self.router_table[destination_router_id] = next_hop
            else:
                # 没有下一跳,该路由器是目标路由器本身
                self.router_table[destination_router_id] = destination_router_id

    # 添加链路状态
    def add_linkstate(self, nearby_router_id, cost):
        if self.router_id not in self.link_state_database:
            self.link_state_database[self.router_id] = {}
        self.link_state_database[self.router_id][nearby_router_id] = cost

        if nearby_router_id not in self.link_state_database:
            self.link_state_database[nearby_router_id] = {}
        self.link_state_database[nearby_router_id][self.router_id] = cost

    # 发送链路状态
    def send_link_state_update(self):  # 发送链路状态更新报文给相邻路由器
        for neighbor_router_id in self.link_state_database[self.router_id]:
            link_state_info = self.link_state_database[self.router_id]
            self.log_queue.put((self.router_id, neighbor_router_id, link_state_info))

    # 接收路由更新
    def receive_link_state_update(self, source_router_id, link_state_info):
        self.link_state_database[source_router_id] = link_state_info

    # 处理帧
    def process_frame(self, frame, source_mac):

        # 解析以太网帧,提取数据部分
        data = frame["data"]
        if isinstance(data, dict):
            # 处理ARP分组
            if "opcode" in data:
                self.process_arp_packet(data, source_mac)
            # 处理IPv4分组
            elif "source_ip" in data and "destination_ip" in data:
                self.process_ipv4_packet(data)
            # 处理ICMP分组
            elif "ICMP" in data:
                self.process_icmp_packet(data)
            # 处理其他类型的分组
            else:
                log_message = f"No action taken for unknown packet on {self.router_id}"
                print(log_message)
        else:
            log_message = f"No action taken for unknown packet on {self.router_id}"
            print(log_message)

    # 处理ARP报文
    def process_arp_packet(self, packet, source_mac):
        # 解析ARP分组
        source_ip = packet["source_ip"]
        target_ip = packet["target_ip"]

        # 处理ARP请求
        if packet["opcode"] == "request":  # ARP请求
            # 判断目标IP地址是否为当前路由器的接口IP地址
            if target_ip in self.arp_table:
                # 构造ARP响应
                arp_response = {
                    "opcode": "reply",
                    "source_ip": target_ip,
                    "source_mac": self.arp_table.get(target_ip),
                    "target_ip": source_ip,
                }

                # 构造以太网帧
                ethernet_frame = {
                    "destination_mac": source_mac,
                    "source_mac": self.router_mac,
                    "data": arp_response
                }

                # 发送以太网帧
                self.log_queue.put(ethernet_frame)
                return

        elif packet["opcode"] == "reply":
            self.add_arp(packet["source_ip"], packet["source_mac"])
            if target_ip == self.router_id:
                log_message = f"{self.router_id} get arp_reply"
                print(log_message)
            else:
                next_hop = self.router_table.get(target_ip)
                if next_hop:
                    ethernet_frame = {
                        "source_mac": self.router_id,
                        "destination_mac": self.arp_table.get(next_hop),
                        "data": packet
                    }
                    self.log_queue.put(ethernet_frame)
            return

    # 处理IPV4报文
    def process_ipv4_packet(self, packet):
        destination_ip = packet["destination_ip"]

        if destination_ip == self.router_id:
            receives = packet["data"]
            log_message = f"{self.router_id} got IPv4 packet: \n{receives}"
            print(log_message)
            return

        # 进行IP路由选择
        next_hop = self.router_table.get(destination_ip)
        if next_hop:
            ethernet_frame = {
                "source_mac": self.router_id,
                "destination_mac": self.arp_table.get(next_hop),
                "data": packet
            }
            self.log_queue.put(ethernet_frame)

    # 处理ICMP报文
    def process_icmp_packet(self, packet):
        source_ip = packet["source_ip"]
        destination_ip = packet["destination_ip"]
        icmp_type = packet["ICMP"]

    def process_frames(self):
        for port, message_queue in self.frame_queue.items():
            print(f"Key: {port}, Value: {message_queue}")
            while True:
                if not message_queue.empty():
                    frame = message_queue.get()
                    print("--路由器接收报文--")
                    self.process_frame1(frame, port)

    def process_frame1(self, frame, in_port):
        # 解析报文 暴露网络层
        # 根据目的IP,与子网掩码相与,得到网络号
        # 根据得到的网络号逐条比对路由表,若存在多条符合,则遵循最长前缀匹配
        # 符合,则转发至相应端口,不符合,则丢弃
        print("--这里是路由器接收--")
        print(frame)
        print("---")
        ip_packet = frame.data.data
        des_ip = ip_packet.d_ip
        print("--这里是目的网络地址--")
        print(des_ip, type(des_ip))
        # 根据端口号查询子网掩码
        mask = get_mask_by_number(self.router_port, in_port)
        print("--这里是子网掩码--")
        net_num = bitwise_and_binary_to_decimal(des_ip, ipv4_to_binary(mask))
        # 查询路由表 进行转发操作,直接转发至端口的交换机/路由器
        for entry in self.router_table:
            if entry.net_num == net_num:
                # 执行转发操作
                print(f"Forwarding packet to {net_num} via next hop: {entry.nextHop},port:{entry.port}")
                # 获取到了端口号,给端口对应的交换机队列放进去消息
                self.forward_queue[str(entry.port)].put(frame)
                print(self.forward_queue[str(entry.port)])
                return
        print(f"路由表中并无此网络: {net_num}")
        pass

    def run(self):  # 路由器实际运行
        while True:
            self.process_frames()
            print("Router is running")
            time.sleep(1)
            with self.lock:
                print("Router is running")
        # self.add_arp(self.router_id, self.router_mac)
        # self.build_routing_table()
        # while True:
        #     # 处理接收到的消息
        #     try:
        #         frame = self.log_queue.get(timeout=1)
        #         if frame["destination_mac"] == self.router_mac:
        #             # 收到目标为自己的消息,处理数据包
        #             self.process_frame(frame, frame["source_mac"])
        #         elif frame["destination_mac"] == '000':
        #             self.process_frame(frame, frame["source_mac"])
        #         else:
        #             self.log_queue.put(frame)
        #     except queue.Empty:
        #         # 队列为空,继续下一轮循环
        #         pass
        #     except TypeError:
        #         pass


# 交换机
class Switch(threading.Thread):
    def __init__(self, name, mac_table, forward_table, router, router_queue):
        super().__init__()
        self.name = name
        self.num_ports = 4  # 默认端口存在4个
        self.mac_table = mac_table  # 构建的路由器是二层路由器,所以只存在mac_table
        self.frame_queue = queue.Queue()  # 报文队列用于缓存所有接收到的数据帧
        self.router_queue = router_queue
        self.forward_queue = forward_table
        self.router = router
        self.lock = threading.Lock()

    def print_macTable(self):  # 测试代码
        print("--打印交换表--")
        for mac in self.mac_table:
            print('%#x' % mac)
        print("--打印交换表结束--")

    def run(self):
        # 交换机线程执行的主体逻辑
        while True:
            self.process_frames()
            time.sleep(1)  # 模拟交换机的持续运行
            with self.lock:
                print("Switch is running...")

    # 登记源mac地址到mac表
    def learn_mac_address(self, mac_address, port):
        with self.lock:
            self.mac_table[mac_address] = port

    # 处理帧缓存队列
    def process_frames(self):
        while True:
            if not self.frame_queue.empty():
                frame = self.frame_queue.get()
                # 出队
                print(f"{self.name}--交换机打印--")
                print(frame)
                self.process_frame1(frame, "1")
            if not self.router_queue.empty():
                frame = self.router_queue.get()
                # 出队
                print(f"{self.name}--交换机打印--")
                print(frame)
                self.process_frame1(frame, "1")

    def process_frame1(self, frame, in_port):
        source_mac = frame.s_mac
        # dest_mac = hex(frame.d_mac)
        dest_mac = frame.d_mac
        print(dest_mac)
        print(self.mac_table)
        # print(f"这里是交换机{'%#x' %dest_mac}")
        # print(f"这里是交换机{hex(dest_mac)}")
        with self.lock:
            print("进入")
            # 因为将所有的端口信息都给了switch 所以以下第一种情况不会发生
            # if source_mac not in self.mac_table:
            #     # 如果源MAC地址不在表中,学习该地址和端口的映射关系
            #     self.learn_mac_address(source_mac, in_port)

            if self.mac_table.get(dest_mac):
                # 目标MAC地址已知,直接转发到相应端口
                print("转发")
                out_port = self.mac_table[dest_mac]
                self.send_frame(frame, out_port)
            else:
                print("失败")
                # 目标MAC地址未知,广播数据帧到所有端口
                self.broadcast_frame(frame, in_port)

    # 转发以太网帧
    def process_frame(self, source_mac, dest_mac, data, in_port):
        with self.lock:
            # 因为将所有的端口信息都给了switch 所以以下第一种情况不会发生
            if source_mac not in self.mac_table:
                # 如果源MAC地址不在表中,学习该地址和端口的映射关系
                self.learn_mac_address(source_mac, in_port)

            if dest_mac in self.mac_table:
                # 目标MAC地址已知,直接转发到相应端口
                out_port = self.mac_table[dest_mac]
                self.send_frame(data, out_port)
            else:
                # 目标MAC地址未知,广播数据帧到所有端口
                self.broadcast_frame(data, in_port)

    # 发送以太网帧
    def send_frame(self, frame, out_port):
        print("--发送以太网帧--")
        print(f"Switch sending frame to port {out_port}: {frame.data}")
        self.forward_queue[frame.d_mac].put(frame)
        print("--发送成功--")

    def add_frame_queue(self, frame):
        self.frame_queue.put(frame)
        print("--打印目的mac---")
        print('%#x' % frame.d_mac)
        print("--打印完毕--")

    # 广播发送
    def broadcast_frame(self, data, in_port):
        print("--广播发送--")
        in_port_mac = get_keys_except_value(self.mac_table, int(in_port))
        print(in_port_mac, in_port)
        for mac in in_port_mac:
            print('%#x' % mac)
            self.forward_queue[mac].put(data)
        print("--广播完毕--")

    # 由端口号获取端口
    def get_switch_port(self, port_number):
        return SwitchPort(self, port_number)


# 主机
class Host(threading.Thread):
    def __init__(self, mac_address, ip_address, switch, port_number, receive_queue):
        super().__init__()
        self.mac_address = mac_address
        self.ip_address = ip_address
        self.arp_table = {}
        self.switch = switch
        self.connected_port = None
        self.port_number = port_number
        self.receive_queue = receive_queue or queue.Queue()
        self.lock = threading.Lock()

    # 添加arp表记录
    def add_arp(self, arp_ip, arp_mac):
        self.arp_table[arp_ip] = arp_mac

    # 查询arp表
    def query_arp(self, des_ip):
        if des_ip in self.arp_table:
            result = self.arp_table[des_ip]
            return result
        else:
            return None

    # 以太网帧构造
    def constructingEthernetFrame(self, dec_mac, type, data):
        print("---生成以太网帧---")
        return EthernetFrame(dec_mac, self.mac_address, type, data)

    # IPV4报文构造
    def constructIPV4Message(self, tos, id_num, flags, fragment, ttl, protocol, checksum, d_ip, data):
        print("---生成IPV4报文---")
        return IPV4(tos, id_num, flags, fragment, ttl, protocol, checksum, self.ip_address, d_ip, data)

    # ARP报文构造
    def constructARPMessage(self, op_type, dec_mac, dec_ip):
        A = ARP(op_type, self.mac_address, self.ip_address, dec_mac, dec_ip)
        print("---生成ARP报文---")
        return ARP(op_type, self.mac_address, self.ip_address, dec_mac, dec_ip)

    # ICMP报文构造
    def constructICMPMessage(self, type, code, data):
        print("---生成ICMP报文---")
        return ICMP(type, code, data)

    def run(self):
        # 主机线程执行的主体逻辑
        while True:
            time.sleep(2)  # 模拟主机的持续运行
            if not self.receive_queue.empty():
                packet = self.receive_queue.get()
                self.process_packet(packet)
                print(self.receive_queue)
            with self.lock:
                print(f"Host {'%#x' % self.mac_address} is running...")

    def process_packet(self, packet):
        print("--开始接收报文--")
        print(f"{'%#x' % self.mac_address} received a packet from {'%#x' % packet.s_mac}: {packet.data.data.data}")
        print("--接收成功--")

    # 与switch建立连接
    def connect_to_switch(self):
        with self.lock:
            self.connected_port = self.switch.get_switch_port(self.connected_port)

    def send_data(self, dest_mac, data):
        with self.lock:
            if self.connected_port is not None:
                print(f"Host {'%#x' % self.mac_address} sending data to {'%#x' % dest_mac}: {data}")
                self.connected_port.process_frame(self.mac_address, dest_mac, data)
            else:
                print("Host not connected to switch.")

    def send_packet(self, des_mac, des_ip, sdu):
        with self.lock:
            if self.connected_port is not None:
                ipv4_frame = IPV4(0x06, self.ip_address, des_ip, sdu)
                mac_frame = EthernetFrame(des_mac, self.mac_address, 0x0800, ipv4_frame)
                self.connected_port.process_frame(self.mac_address, des_mac, mac_frame)
            else:
                print("Host not connected to switch.")

    def sendFrame(self, des_ip, sdu):
        print(f"Host {'%#x' % self.mac_address} sending data")
        des_mac = self.query_arp(des_ip)
        print("检查本机ARP缓存")
        if des_mac is None:
            print("目的MAC地址未找到")
            arp_frame = ARP(0x01, self.mac_address, self.ip_address, "", des_ip)
            mac_frame = EthernetFrame("", self.mac_address, 0x0806, arp_frame)
            return mac_frame
        else:
            print('目的MAC地址已找到')
            ipv4_frame = IPV4(0x06, self.ip_address, self.mac_address, sdu)
            mac_frame = EthernetFrame(des_mac, self.mac_address, 0x0800, ipv4_frame)
            return mac_frame


# 交换机端口
class SwitchPort:
    def __init__(self, switch, port_number):
        self.switch = switch
        self.port_number = port_number

    def process_frame(self, source_mac, dest_mac, data):
        self.switch.add_frame_queue(EthernetFrame(dest_mac, source_mac, 0x0600, data))
        # self.switch.process_frame(source_mac, dest_mac, data, self.port_number)


# 接收消息提取队列
switch_queue = queue.Queue()
host1_queue = queue.Queue()
host2_queue = queue.Queue()
host3_queue = queue.Queue()
# 路由器发送、交换机提取的队列
switch1_queue = queue.Queue()
host4_queue = queue.Queue()
host5_queue = queue.Queue()
host6_queue = queue.Queue()
# 交换机发送、路由器提取的队列
router1_queue_sw1 = queue.Queue()
router1_queue_sw2 = queue.Queue()

router1_table = [
    RouterTableEmit("192.168.0.0", "255.255.255.128", "192.168.0.126", 1), # 端口1
    RouterTableEmit("192.168.0.128", "255.255.255.128", "192.168.0.254", 2), # 端口2
    RouterTableEmit("192.168.0.130", "255.255.255.128", "192.168.0.254",2) # 端口2
]

# 路由器1 端口0:192.168.0.126 端口1:192.168.0.254
router1_port = {RouterPort("1", "192.168.0.126", "255.255.255.128"),
                RouterPort("2", "192.168.0.254", "255.255.255.128")}
forward_table1 = {"1": switch_queue, "2": switch1_queue}
frame_queue = {"1": router1_queue_sw1, "2": router1_queue_sw2}
router1 = Router(0x001122334451, ipv4_to_binary("192.168.0.126"), forward_table1, router1_port, frame_queue, router1_table)
router1.print_queue()
# 交换机初始交换表
mac_table = {0x001122334455: 1, 0xaabbccddeeff: 2, 0xaabbccddee11: 3, 0x001122334451: 4}
mac_table1 = {0x111111111111: 1, 0x222222222222: 2, 0x333333333333: 3, 0x001122334451: 4}

# 交换机连接的实体的消息接收队列
forward_table = {0x001122334455: host1_queue, 0xaabbccddeeff: host2_queue, 0xaabbccddee11: host3_queue,
                 0x001122334451: router1_queue_sw1}
forward_table1 = {0x111111111111: host4_queue, 0x222222222222: host5_queue, 0x333333333333: host6_queue,
                  0x001122334451: router1_queue_sw2}

# 子网0 网络号:192.168.0.0 子网掩码:255.255.255.128 网关:192.168.0.126

# 交换机0 实体
switch = Switch("sw0", mac_table, forward_table, router1, switch_queue)
# 主机实体
host1 = Host(0x001122334455, ipv4_to_binary("192.168.0.1"), switch, "1", host1_queue)
host2 = Host(0xaabbccddeeff, ipv4_to_binary("192.168.0.2"), switch, "2", host2_queue)
host3 = Host(0xaabbccddee11, ipv4_to_binary("192.168.0.3"), switch, "3", host3_queue)

# 子网1 网络号:192.168.0.128 子网掩码:255.255.255.128 网关:192.168.0.254
# 交换机1 实体
switch1 = Switch("sw1", mac_table1, forward_table1, router1, switch1_queue)
# 主机实体
host4 = Host(0x111111111111, ipv4_to_binary("192.168.0.129"), switch1, "1", host4_queue)
host5 = Host(0x222222222222, ipv4_to_binary("192.168.0.130"), switch1, "2", host5_queue)
host6 = Host(0x333333333333, ipv4_to_binary("192.168.0.131"), switch1, "3", host6_queue)

# 将主机连接到交换机
host1.connect_to_switch()
host2.connect_to_switch()
host3.connect_to_switch()
host4.connect_to_switch()
host5.connect_to_switch()
host6.connect_to_switch()

router1.start()
switch.start()  # 启动交换机0线程
switch1.start()  # 启动交换机1线程
host1.start()  # 启动主机1线程
# host2.start()  # 启动主机2线程
# host3.start()  # 启动主机3线程
# host4.start()  # 启动主机4线程
host5.start()  # 启动主机5线程
# host6.start()  # 启动主机6线程

# 单播数据发送
# host1.send_data(0xaabbccddeeff, "Hello from Host 1 to Host 2")
# host2.send_data(0x001122334455, "Hello from Host 2 to Host 1")
# 广播数据发送
# host1.send_data(0xaabbccddeef1, "Hello from Host 1 to Host 2")
host1.send_packet(0x222222222222, ipv4_to_binary("192.168.0.130"), "Hello from Host 1 to Host 5")

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值