AE 7001
2
BW 3.1 7003
DR 2.7 7007
windows下运行启动脚本:
start cmd /k "python router.py configAE.txt"
代码文件router.py
#!/usr/bin/python3.7
import socket
import sys
import threading
import time
import operator
import copy
# 获取精度到秒的时间戳
def get_time():
return int(time.time())
# 创建发送的信息
def create_msg():
msg = router_id + ' ' + str(router_port) + ' ' + str(get_time()) + '\n'
msg = msg + "neighbour\n"
for ID in neighbour_list.keys():
msg = msg + ID + ' ' + str(neighbour_list[ID].get_port()) + ' '\
+ str(neighbour_list[ID].get_cost()) + '\n'
return msg
# 读取接收的信息
def deal_msg(msg):
if msg == "":
return -1
lines = msg.split("\n")
creater = lines[0].split(" ")
creater_id = creater[0]
creater_port = creater[1]
creater_time = int(creater[2])
# if it is created by itself
if creater_id == router_id:
return -1
# if it is a path information
if lines[1] == "neighbour":
# if it is a recur router
if creater_id in dead_list:
router_recieve_list[creater_id] = creater_time
dead_list.remove(creater_id)
temp_dic = {}
for line in lines[2:-1]:
info = line.split(" ")
temp_dic[info[0]] = [int(info[1]),float(info[2])]
if operator.eq(temp_dic, all_route[creater_id]) != 0:
all_route[creater_id] = temp_dic
return creater_id
# if it is a new router
if creater_id not in router_recieve_list.keys()\
or creater_id not in all_route.keys():
router_recieve_list[creater_id] = creater_time
temp_dic = {}
for line in lines[2:-1]:
info = line.split(" ")
temp_dic[info[0]] = [int(info[1]),float(info[2])]
all_route[creater_id] = temp_dic
return 0
# if just normal update
else:
# if it is an old message which do not need to deal with
if creater_time <= router_recieve_list[creater_id]:
return -1
# if it is a useful message
else:
router_recieve_list[creater_id] = creater_time
temp_dic = {}
for line in lines[2:-1]:
info = line.split(" ")
temp_dic[info[0]] = [int(info[1]),float(info[2])]
if operator.eq(temp_dic, all_route[creater_id]) == 0:
return 0 # do nothing
# replace it
else:
all_route[creater_id] = temp_dic
return 0
elif lines[1] == "dead":
if creater_id not in router_recieve_list.keys():
router_recieve_list[creater_id] = creater_time
elif creater_time <= router_recieve_list[creater_id]:
return -1
if lines[2] not in dead_list and lines[2] != router_id:
dead_list.append(lines[2])
return 0
elif lines[1] == "resur":
if creater_id not in router_recieve_list.keys():
router_recieve_list[creater_id] = creater_time
elif creater_time <= router_recieve_list[creater_id]:
return -1
if lines[2] in dead_list:
dead_list.remove(lines[2])
return 0
# Dijkstra算法与打印输出
def Dijkstra():
# delete all the dead route
temp_routers = copy.deepcopy(all_route)
for ID in dead_list:
if ID != router_id:
if ID in temp_routers.keys():
del temp_routers[ID]
for router in temp_routers.keys():
if ID in temp_routers[router].keys():
del temp_routers[router][ID]
# start caculate
unvisit_nodes = [ID for ID in temp_routers.keys()]
visited_nodes = []
# initialize
for ID in unvisit_nodes:
# {ID: previous node, cost}
cost_list[ID] = ['', float('inf')]
# first point
cost_list[router_id] = ['', 0.0]
# all neighbours
for ID in all_route[router_id].keys():
cost_list[ID] = [router_id, all_route[router_id][ID][1]]
unvisit_nodes.remove(router_id)
visited_nodes.append(router_id)
# start loop
while len(unvisit_nodes) != 0:
# find the shortest unvisit node
min_cost = float('inf')
min_id = ''
for ID in unvisit_nodes:
if cost_list[ID][1] <= min_cost:
min_cost = cost_list[ID][1]
min_id = ID
# start from min_id, for all neighbours
for ID in all_route[min_id].keys():
if ID in unvisit_nodes:
cost = round(min_cost + all_route[min_id][ID][1], 6)
# if it is a shorter path
if cost < cost_list[ID][1]:
cost_list[ID] = [min_id, cost]
# mark the node
unvisit_nodes.remove(min_id)
visited_nodes.append(min_id)
# print result
print("I am Router " + router_id)
visited_nodes.remove(router_id)
visited_nodes.sort()
for ID in visited_nodes:
path = ID
temp = ID
while cost_list[temp][0] != '':
path = cost_list[temp][0] + path
temp = cost_list[temp][0]
print("Least cost path to router " + ID + ": " \
+ path + " and the cost is " + str(cost_list[ID][1]))
print()
# 为记录中的路由器创建一个类来记录
class router:
def __init__(self, ID, cost, port):
self.ID = ID
self.cost = cost
self.port = port
def get_id(self):
return self.ID
def get_cost(self):
return self.cost
def get_port(self):
return self.port
# 广播线程
class broadcast(threading.Thread):
def __init__(self, threadID, name, interval, soc):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.interval = interval
self.soc = soc
def run(self):
while True:
msg = create_msg()
msg = msg.encode(encoding='UTF-8')
for ID in neighbour_list.keys():
self.soc.sendto(msg, ("127.0.0.1", neighbour_list[ID].get_port()))
time.sleep(self.interval)
# 接收线程
class recieve(threading.Thread):
def __init__(self, threadID, name, soc):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.soc = soc
def run(self):
while True:
msg = ""
addr = ""
try:
data, addr = self.soc.recvfrom(2048)
msg = data.decode(encoding='UTF-8')
except:
pass
#print(msg,"from",addr)
result = deal_msg(msg)
if result == 0: # if it is not an old message, broadcast it
for ID in neighbour_list.keys():
self.soc.sendto(data, ("127.0.0.1", neighbour_list[ID].get_port()))
# some router is recur
elif type(result) == str:
recur_msg = router_id + ' ' + str(router_port) + ' ' + str(get_time()) + '\n'
recur_msg = recur_msg + "resur\n" + result + "\n"
recur_msg = recur_msg.encode(encoding='UTF-8')
for ID in neighbour_list.keys():
self.soc.sendto(recur_msg, ("127.0.0.1", neighbour_list[ID].get_port()))
# for test
#print(msg,"deal with from",addr)
# 计算线程
class calculate(threading.Thread):
def __init__(self, threadID, name, soc):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.soc = soc
def run(self):
while True:
time.sleep(ROUTE_UPDATE_INTERVAL)
now = get_time()
for ID in neighbour_list.keys():
# if a router is dead
if ID in router_recieve_list.keys():
if now - router_recieve_list[ID] > 10 and ID not in dead_list:
dead_list.append(ID)
dead_msg = router_id + ' ' + str(router_port) + ' ' + str(get_time()) + '\n'
dead_msg = dead_msg + "dead\n" + ID + "\n"
dead_msg = dead_msg.encode(encoding='UTF-8')
for ID in neighbour_list.keys():
self.soc.sendto(dead_msg, ("127.0.0.1", neighbour_list[ID].get_port()))
Dijkstra()
# 读取文件信息
filepath = sys.argv[1]
# set parameter
UPDATE_INTERVAL = 1
ROUTE_UPDATE_INTERVAL = 30
router_id = 0
router_port = 0
# total number of neighbours
neighbour_number = 0
# {ID: class router}, only for neighbours
neighbour_list = {}
# {ID: timestamp}, last time recieve broadcast created by the router
router_recieve_list = {}
# all routers in the whole net
# like {A: {B:[5001,2],C:[5003,5]}}, means A to B is 2, only A's neighbours
all_route = {}
# dead router
dead_list = []
# # {ID: previous node, cost}, store the result of Dijkstra’s algorithm
cost_list = {}
with open(filepath) as input_file:
input_lines = input_file.readlines()
router_id = input_lines[0].split(" ")[0]
router_port = int(input_lines[0].split(" ")[1])
neighbour_number = int(input_lines[1])
all_route[router_id] = {}
for i in range(0, neighbour_number):
line = input_lines[i+2]
line = line.split(" ")
neighbour_id = line[0]
neighbour_cost = float(line[1])
neighbour_port = int(line[2])
neighbour_list[neighbour_id] = router(neighbour_id, neighbour_cost, neighbour_port)
all_route[router_id][neighbour_id] = [neighbour_port, neighbour_cost]
# 文件信息读取完毕
# 创建线程
soc = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
soc.bind(("127.0.0.1", router_port))
thread_broadcast = broadcast(1, "broadcast", UPDATE_INTERVAL, soc)
thread_recieve = recieve(2, "recieve", soc)
thread_calculate = calculate(3, "calculate", soc)
# 启动线程
thread_broadcast.start()
thread_recieve.start()
thread_calculate.start()