计算机网络:自顶向下方法 第五章编程作业-DV算法

DV算法(<<计算机网络:自顶向下方法>>第五章编程作业)

目录

DV算(<<计算机网络:自顶向下方法>>第五章编程作业)

一.算法原理

1.1目标

1.2算法的核心思想

1.3算法的表格

1.4“更新”与“发布”

1.5注意事

二.代码部分(以node0.c为例)

 2.1初始化部分

2.2接收到消息

2.3更改链路开销(只在node1.c和node2.c中)

三.测试结果

第一步:初始化

第二步:初始化完成,算法收敛

第三步:更改node0到node1之间的权值,直到算法收敛

第四步:更改回初始状态,直到算法收敛


一.算法原理

1.1目标

     在一个网络中,实现一个 分布式 , 异步 , 迭代 的路由算法.即距离向量(Distance-Vecto算法    

1.2算法的核心思想

     考虑一个网络中的一个 节点 A ,与其直接相邻的邻居节点为   A_{0},A_{1},A_{2}...A_{n} ,目标节点为 B.

     路由算法为: A"询问"其所有邻居结点到B的距离.从中选择 

        A到邻居距离 + 邻居到B距离

 最小的一个邻居.此邻居就是A选择的下一个结点,此值就是A到B的距离.

 将上述语言描述为公式就是:

              

1.3算法的表格

 假设网络中由N个节点,每一个结点需要维护两个表,一个用于存储自己到邻居节点的距离,一个用于存储DV表

 

 以作业中的此图为例,结点0需要维护的第一个表为

 这个表会在初始化中完成,我们认为每一个结点可以知道到其邻居结点的距离,其中的距离是结点到邻居的距离,但不一定是

 最短距离(例如:结点0到结点3的最短距离为4)

 对于无法到达的结点,将其值设为 999。

 注意:除非线路的开销发生了改变,否则这个表是不会变的

 结点需要维护的第二个表就是储存了“询问”结果的表(DV表),这个表的大小是 邻居数*4 ,由于实验中给的此表都是4*4的,有些只使用一部分即可

 以结点0为例,此表为

 这是DV算法收敛时表中的内容,按照实验给出的组织方式 Distance_table[a][b] 就代表了 结点b 结点a 的最小开销。

 可以总结出一些这个表的规律: 

      #1.当算法收敛时,这个表是沿对角线对称的,a到b的距离就是b到a的距离(实验中的网络是无向的)

      #2.表的行数一定4,因为所有的结点个数是4,但列数不固定,是结点的邻居数(自己也加在表里了)

        把不是邻居结点的结点加入列中是没有意义的,因为就算此节点可以到达目的结点,自己也没有办法到达这个结点

 比如说,想要得到从 结点0 到 结点3 的最小开销,查表可得值为 4

 在结点0所维护的表中,如果说知道了第二三四列的值,就可以根据上面提到的公式把第一列给算出来了

 那么,结点1,2,3是怎么知道自己到其他结点的最近距离的呢,答案就是不断的“询问”

 

1.4“更新”与“发布”

 在初始化的时候,每个结点只知道自己到邻居结点的距离,就先将这个填入DV表中,其他的一律填999.以节点0为例,初始化时其DV表 为

 

 每当结点更新了自己到其他结点的距离时,就要通知其邻居结点.发布其最新消息,在这里 结点0 通知 结点1 ,结点2 和 结点3

 通知的内容为自己结点到其他所有结点的距离(就是上图中的第一列,一个四个元素的数组)

 当一个结点收到其邻居结点发来的信息时,就要更新此节点了

 更新策略:其实就是算法的核心公式,举一个例子

                      

                    这是结点1初始化时的表格,4 * 3 代表有2个邻居,在其初始化完后,会向其邻居(0 和 2)发送信息。

                    

                    结点0(初始化是1.4的第一张图),收到了结点1的消息,消息的内容是 1,0,1,999.意思是 

                                          结点 1 到结点 0 的距离是 1

                                          结点 1 到结点 1 的距离是 0

                                          结点 1 到结点 2 的距离是 1

                                          结点 1 到结点 3 的距离是 999(不可达)

                   结点0收到以后,先将其填到第二列,要注意到这时候收到的 结点1 到各个结点的距离不一定是最短的,最短距离有等算法收敛的时候才可以确定。

                   然后,就是更新结点 0 了,因为本来 结点0 到 结点 1 是不可达的,但现在 结点1 可达了,就有可能通过走 节点1 找到一条更短的路。

                                          从  结点 0    经过    结点 1  到    结点0    的距离为:  1 + 1 = 2  <  0  不更新 0,0元素         

                                          从  结点 0    经过    结点 1  到    结点1    的距离为:  1 + 0 = 1  <= 1  不更新 1,0元素

                                          从  结点 0    经过    结点 1  到    结点2    的距离为:  1 + 1 = 2  <  3  更新 2,0元素,初始化的时候是 3,现在是2

                                          从  结点 0    经过    结点 1  到    结点3    的距离为:  1 + 999 = 不可达  <  7  不更新 3,0元素

                  #上面的例子中从  结点0  到  结点1   的距离不是通过DV表来的!!!是查上文第一个表来的(也就是记录了邻居结点距离的1*4表),如果没有这个表,在后续计算中结点到其邻居的距离信息就没有了。

                    比如结点0的DV表把结点0到结点2的距离更新为2了,就是走了 0 -> 1 -> 2这条线路,如果说后来 0->1 的开销变得很大,而结点又没有存储 0->3 距离,那么永远也不会走 0->3 这条线。这就体现了第一个表的重要性

  更新后发布:每个结点其实只可以更改DV表中自己所在的那一列,其他列都依靠别的结点 “告诉” 自己,其他结点告诉自己是多少就是多少,不用且逻辑上也不能去更改。

                       当结点发现DV表中自己所在的那一列被更新了之后,就 “发布” 更新结果(上文所描述的四个元素的数组)给自己所有的邻居。

 

1.5注意事项

      #1,每个节点只与邻居节点通信,且通信的内容仅限于自己到其他所有节点的开销(一个一维数组)

     #2.每次通信都需要与所有的邻居通信

     #3.只要一个节点到其他节点的距离发生改变,就要进行一次通信

     #4.cost(x,v)不是当前节点DV表中存储的值,而是节点直接到其邻居节点的距离信息.

 

二.代码部分(以node0.c为例)

    本实验用的测试框架使用一个 事件列表 来模拟路由器的各种行为。其给定的三个事件为

   

 调用收发函数的时候还会将收发事件插入到事件链表中

  2.1初始化部分

void rtinit0() 
{
  printf("init node0 ... \n");
  init_for_distance_table(dt0.costs);
  dt0.costs[0][THIS_NODE_ID] = 0;
  dt0.costs[1][THIS_NODE_ID] = 1;
  dt0.costs[2][THIS_NODE_ID] = 3;
  dt0.costs[3][THIS_NODE_ID] = 7;
    printdt0(&dt0);
  int node0_init_mincost[4] = { 0 , 1 , 3 , 7};
  node0_comm(node0_init_mincost);
  printf("init node0 finish ... \n \n");
}

  行为:#1.初始化node0的DV表

   #2.调用node0_comm()函数 “发布” 更新消息

void node0_comm(int new_cost[4]){
	struct rtpkt  pkt_2_node1;
	struct rtpkt  pkt_2_node2;
	struct rtpkt  pkt_2_node3;
	creatertpkt(&pkt_2_node1 , THIS_NODE_ID , 1, new_cost);
    creatertpkt(&pkt_2_node2 , THIS_NODE_ID , 2, new_cost);
    creatertpkt(&pkt_2_node3 , THIS_NODE_ID , 3, new_cost);
		printf("node0_comm: create pkt finish \n");
	tolayer2(pkt_2_node1);
    tolayer2(pkt_2_node2);
    tolayer2(pkt_2_node3);
}

 node0_comm()函数就是给结点0的邻居 结点1 ,结点2 ,结点3发送更新,将这个操作写成一个函数,只要node0有更新就调用

2.2接收到消息

void rtupdate0(rcvdpkt)
  struct rtpkt *rcvdpkt;
{
  printf("node 0 recv pkt form node%d...\n",rcvdpkt -> sourceid);
  int is_update = 0;
  int recv_src_id = rcvdpkt -> sourceid; 
  for (int i = 0; i < 4 ; i++)
  {
    dt0.costs[i][recv_src_id] = rcvdpkt -> mincost[i];
    int dis1 = node0_neighbor_distance[i];
    int dis2 = node0_neighbor_distance[1] + dt0.costs[i][1];
    int dis3 = node0_neighbor_distance[2] + dt0.costs[i][2];
    int dis4 = node0_neighbor_distance[3] + dt0.costs[i][3];
    int min_dis = find_min_dis(dis1,dis2,dis3,dis4);
    if (dt0.costs[i][THIS_NODE_ID] != min_dis){ //节点有变化就要发送
      is_update = 1;
    }
    dt0.costs[i][THIS_NODE_ID] = min_dis;
  }
  if (is_update) //如果节点有更新,那么就要通知所有的邻居节点
  {
	int new_cost[4] = {  dt0.costs[0][THIS_NODE_ID] ,dt0.costs[1][THIS_NODE_ID] 
						          ,dt0.costs[2][THIS_NODE_ID] ,dt0.costs[3][THIS_NODE_ID]};
	node0_comm(new_cost);
  }
  printdt0(&dt0);
  printf("\n");
}

 dis1到4分别为1.4中描述的那四个距离,返回其最小值,就算是一次更新了,如果结果没有变化,就不发布新消息,否则,就要通知全部邻居结点.node_neighbor_distance就是1.3中第一个表

  2.3更改链路开销(只在node1.c和node2.c中)

linkhandler0(linkid, newcost)   
  int linkid, newcost;
{
	printf("node0 recv link cost change: 0 -> %d = %d \n",linkid,newcost);
	dt0.costs[linkid][THIS_NODE_ID] = newcost;
	node0_neighbor_distance[1] = newcost;
	int new_cost[4] = {  dt0.costs[0][THIS_NODE_ID] ,dt0.costs[1][THIS_NODE_ID] 
						,dt0.costs[2][THIS_NODE_ID] ,dt0.costs[3][THIS_NODE_ID]};
	node0_comm(new_cost);
}

  行为:#1.更改DV表,更改node_neighbor_distance表

         #2.发布更新

 

三.测试结果

第一步:初始化

 

第二步:初始化完成,算法收敛

     此时的路由器状态为:

 

 

第三步:更改node0到node1之间的权值,直到算法收敛

此时路由器状态为

 

第四步:更改回初始状态,直到算法收敛

 

后记:在网上没有找到这个这个实验的博客,就自己写一个吧.有什么错误欢迎大家指出

 

  • 5
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值