我无法使代码正常工作,因此成本增加。我在代码中使用以下功能:
UpdateRouteCost:此命令采用两个参数,邻居名称和成本。例如,当用户输入命令UpdateRouteCost nodeB 4时,您的程序应该能够将与此节点到nodeB的对应链接成本更新为4。
ReConstructRoutingTable:这是用于执行BellmanFord算法并基于UpdateRouteCost更新路由表或从邻居那里获取更新的函数。
SendUpdate:只要节点更新了路由表,就应该调用此函数。
HandleMessage:每当节点收到邻居的消息时,都应调用此函数。
要运行代码,必须同时打开python3 node.py a.ini python3 node.py b.ini python3 node.py c.ini来同时打开所有3个节点。然后,您可以更新成本和路由表。
python 3中的node.py
import socket
import json
import operator
import sys
import binascii
import struct
import threading
import configparser
def is_diff(obj1,obj2):
if obj1 == None or obj2 == None:
return False
for k in obj1:
if k == 'node':
continue
if obj1[k]['cost'] != obj2[k]['cost']:
return True
return False
def print_table(obj):
if obj == None:
print(">>>>>> table is empty <<<<<<<<")
return
dest1 = obj['link1']['name']
cost1 = obj['link1']['cost']
next_hop1 = obj['link1']['name']
dest2 = obj['link2']['name']
cost2 = obj['link2']['cost']
next_hop2 = obj['link2']['name']
print('>>>> ' + obj['node']['name'] + ' routing table <<<<')
print('-------------------------------------------------------')
print('| destination | link cost | next hop |')
print('| %-13s| %-13s| %-13s|' % (dest1,cost1,next_hop1))
print('| %-13s| %-13s| %-13s|' % (dest2,cost2,next_hop2))
print('-------------------------------------------------------')
def print_diff(obj1,obj2):
if obj1 == None or obj2 == None:
return
if is_diff(obj1,obj2):
print("Before Update Table")
print_table(obj1)
print("After Update Table")
print_table(obj2)
for k in obj1:
if k == "node":
continue
if obj2[k]['cost'] != obj1[k]['cost']:
print("Node " + obj2[k]['name'] + " cost changed from " + str(obj1[k]['cost']) + " to " + str(obj2[k]['cost']))
else:
print("Node " + obj1['node']['name'] + " routing table not changed")
def save_table(table):
global node_configs
node_configs[table['node']['name']] = table
def listen_thread(port):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(("0.0.0.0", port))
while True:
data, addr = s.recvfrom(1024)
print(data)
class RecvThread(threading.Thread):
def __init__(self,port):
super(RecvThread, self).__init__()
self.port = port
def run(self):
global node_configs
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(("0.0.0.0", self.port))
while True:
data, addr = s.recvfrom(1024)
print("Recv: ");
dict = json.loads(str(data,encoding='utf-8'))
print_table(dict)
name = dict['node']['name']
old = None
if name in node_configs:
old = node_configs[name]
save_table(dict)
print_diff(old,dict)
handle_message(dict)
print("Input command(FirstLoad,FirstSend,Bye,MyRoutingTable,UpdateRouteCost):")
class MyParser(configparser.ConfigParser):
def as_dict(self):
d = dict(self._sections)
for k in d:
d[k] = dict(d[k])
d[k].pop('__name__', None)
return d
if len(sys.argv) != 2:
print("Useage: python " + sys.argv[0] + " <confg file>")
sys.exit(-1)
def load_ini(file):
cf = MyParser()
cf.read(file)
return cf.as_dict()
config_dict = load_ini(sys.argv[1])
listen_port = int(config_dict['node']['port'])
#run recv thread
t = RecvThread(int(listen_port))
t.setDaemon(True)
t.start()
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
node_configs = {}
def reconstruct(obj):
change = False
name1 = config_dict['node']['name']
name2 = obj['node']['name']
for j in config_dict:
if config_dict[j]['name'] == name2:
link = j
cost = int(config_dict[j]['cost'])
for k in obj:
link = obj[k]
link_name = link['name']
if k == "node":
continue
else:
for i in config_dict:
test_node = config_dict[i]
test_name = test_node['name']
if i == "node":
continue
elif test_name == name2 and link_name == name1:
if test_node['cost'] != link['cost']:
test_node['cost'] = link['cost']
change = True
elif test_name == link_name:
a = int(test_node['cost'])
b = int(link['cost']) + cost
if a > b:
test_node['cost'] = b
change = True
if change:
send()
def handle_message(obj):
reconstruct(obj)
def send():
global s
#send to link1
s.sendto(bytes(json.dumps(config_dict),'utf8'),(config_dict['link1']['ip'],int(config_dict['link1']['port'])))
#send to link2
s.sendto(bytes(json.dumps(config_dict),'utf8'),(config_dict['link2']['ip'],int(config_dict['link2']['port'])))
print("Send config finished")
def load(ini):
config_dict = load_ini(ini)
print("Load config file finished")
def update_cost(node,cost):
if not cost.isdigit():
print("Cost is not number")
return
found = False
for k in config_dict:
if k == "node":
continue
v = config_dict[k]
tmp_name = v['name']
if tmp_name == node:
v['cost'] = cost
found = True
if not found:
print("Node <" + node + "> not found in table")
else:
send()
while True:
print("Input command(FirstLoad,FirstSend,Bye,MyRoutingTable,UpdateRouteCost):")
text = sys.stdin.readline().strip()
if text == "FirstSend":
send()
elif text == "FirstLoad":
load(sys.argv[1])
elif text == "Bye":
break
elif text == "MyRoutingTable":
print_table(config_dict)
elif text.startswith("UpdateRouteCost"):
cmds = text.split(" ")
if len(cmds) != 3:
print("Update command usage:UpdateRouteCost <node name> <cost>")
continue
name = cmds[1]
cost = cmds[2]
update_cost(name,cost)
else:
print("Invalid command")
a.ini
[node]
name=nodeA
port=1025
[link1]
name=nodeB
ip=127.0.0.1
port=1027
cost=4
[link2]
name=nodeC
ip=127.0.0.1
port=1029
cost=10
b.ini
[node]
name=nodeB
port=1027
[link1]
name=nodeA
ip=127.0.0.1
port=1025
cost=4
[link2]
name=nodeC
ip=127.0.0.1
port=1029
cost=1
c.ini
[node]
name=nodeC
port=1029
[link1]
name=nodeB
ip=127.0.0.1
port=1027
cost=1
[link2]
name=nodeA
ip=127.0.0.1
port=1025
cost=10