在距离矢量路由协议中实现Bellman Ford算法

时间:2019-04-11 17:09:37

标签: python sockets udp nodes bellman-ford

我无法使代码正常工作,因此成本增加。我在代码中使用以下功能:

  1. UpdateRouteCost:此命令采用两个参数,邻居名称和成本。例如,当用户输入命令UpdateRouteCost nodeB 4时,您的程序应该能够将与此节点到nodeB的对应链接成本更新为4。

  2. ReConstructRoutingTable:这是用于执行BellmanFord算法并基于UpdateRouteCost更新路由表或从邻居那里获取更新的函数。

  3. SendUpdate:只要节点更新了路由表,就应该调用此函数。

  4. 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

0 个答案:

没有答案