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