计算机网络实验三(java代码实现RIP)

1.距离向量算法

距离向量路由算法要求,每个结点都参与定期交换整个路由表,即把路由表传递给自己与之相连的结点。
首先,当前路由表的组成如下,<目的网络 N,跳数,下一跳地址>

1.1.执行步骤

  1. 从相邻的 X 路由器接收发送过来的 RIP(Routing Information Protocol) 报文
  2. 将该 RIP 报文中的下一跳地址修改为 X,且跳数增加 1
  3. 对每个项目执行如下步骤
    a.若原路由表没有 RIP 中的目的网络 N,直接添加到原路由表中
    b.若原路由表中有 RIP 中的目的网络 N,但下一跳地址不是 X ,选择跳数少的替换。如果两者跳数一样,则保留原路由表的项。
    c.若原路由表中有 RIP 中的目的网络 N,且下一跳地址是 X,使用收到的项替换
  4. 若超过 180s (RIP 默认 180s)还没有收到相邻路由器的更新路由表,则相邻路由器置为不可达,跳数为 16

算法的缺点:可以看到,距离向量协议传送的是整个路由表,那么报文的大小就和通信子网的结点个数成正比,如果通信子网越大,那么报文也将非常大。
PS:实际运用中,RIP算法只关心跳数,并不关心带宽,反而有可能避开了最有的路线。

2.实验讲义

2.1.讲义截图

在这里插入图片描述

2.2.实验要求

在这里插入图片描述

3.代码实现

3.1.路由类(用来表示单条路由)

public class Rip {
    private String  netto;//目的网络
    private int number;//目的 网络号 数字类型
    private Integer distance;//距离
    private String next;//下一跳
    public int getNumber(){//用来排序
        String number = this.netto;//拷贝一个副本
        int ret;
        return  ret = Integer.parseInt(number.replaceAll("N",""));
    }
    @Override
    public String toString() {
        return netto + "          " +
                         + distance +"        "+
                  next
                ;
    }
    public String getNetto() {
        return netto;
    }
    Rip (String netto,int distance,String next){
        this.netto = netto;
        this.distance = distance;
        this.next = next;
    }
    Rip (String netto,int distance){
        this.netto = netto;
        this.distance = distance;
    }
    public void setNetto(String netto) {this.netto = netto;}
    public Integer getDistance() {return distance;   }
    public void setDistance(Integer distance) { this.distance = distance;}
    public String getNext() {return next;}
    public void setNext(String next) {this.next = next;}
    }

3.2.路由表类(用来表示单个路由表)

public class RipTable  {
    private String TableName;//使用private方法,其它类只能通过get set方法调用
    private List<Rip> rips =new ArrayList<Rip>();//存储路由表
    public void print() {
        System.out.println(TableName+"的路由表");
        System.out.println("目的网络"+"\t"+"距离"+"\t"+"下一跳");
        for(Rip rip:rips){
            System.out.println(rip.toString());
        }
    }
    public void clear(){
        rips.clear();
    }
    RipTable(String tableName){//用于设置路由器名
        this.TableName = tableName;
    }
    public List<Rip> getRips() {
        return rips;
    }

    public String getTableName() {
        return TableName;
    }
}

3.3.路由表一次更新方法

public class UpdateTable_qs1 {
    public static void updateTable(RipTable r1, RipTable r2) {//根据r2更新路由表r1
        HashSet<String> set = new HashSet<String>();
        for (Rip rip : r1.getRips()) {
            set.add(rip.getNetto());//将目的网络加入set表 下面用contain方法判断是否包含
        }
        for (Rip rip : r2.getRips()) {
            rip.setDistance(rip.getDistance() + 1);//将距离+1
            rip.setNext(r2.getTableName());//将r2的下一跳全改为r2的表名
        }
        for (Rip j : r2.getRips()) {//遍历r2路由表
            if (!set.contains(j.getNetto()))//set中不包含的情况
            {
                r1.getRips().add(j);//1、若原路由表没有 RIP 中的目的网络,直接添加到原路由表中
            } else {//2、若原路由表中有 RIP 中的目的网络 N
                for (Rip i : r1.getRips()) {
                    if (i.getNetto().equals(j.getNetto())) {//取到相同的目的网络的位置
                        if (!i.getNext().equals(j.getNext())) {// 但下一跳地址不是 X ,选择跳数少的替换。如果两者跳数一样,则保留原路由表的项
                            if (j.getDistance() < i.getDistance()) {//只有当r2的跳数小于r1时才替换
                                i.setDistance(j.getDistance());//替换跳数
                                i.setNext(j.getNext());//替换下一跳
                            }
                        } else {
                            i.setDistance(j.getDistance());//替换跳数
                            i.setNext(j.getNext());//替换下一跳
                        }
                    }
                }
            }
        }
        Collections.sort(r1.getRips(), new Comparator<Rip>() {//定制排序
            @Override
            public int compare(Rip o1, Rip o2) {
                // TODO Auto-generated method stub
                return o1.getNumber()-o2.getNumber();
            }
        });
        System.out.println("更新后的"+r1.getTableName()+"路由表为:");
        r1.print();
        System.out.println("----------------分割线-------------------");
    }
}

3.4.递归更新到任一目的网络不可达

说明:这里偷懒了,逻辑是r1,r2路由器互相更新,(是所有的目的网络都不可达,同时更新的情况)每一轮次距离增加2,直到任一里面有一个目的网络跳数到达16则输出并返回。

关于要求稳定状态:如果是两个路由表互相更新,当所有网络都不可达(跳数为16)时,也可以视为稳定状态。

public class goodfastbadlast_qs2 {
    public static void updateTable2(RipTable r1, RipTable r2) {//根据r2更新路由表r1
        for(Rip r:r1.getRips()){
            if(r.getDistance()>=16) {
                System.out.println("此时路由表"+r1.getTableName()+"的目的网络"+r.getNetto()+"距离为"+r.getDistance()+"为不可达");
                r1.print();
                return;
            }
        }
        for(Rip r:r2.getRips()){
            if(r.getDistance()>=16){
                System.out.println("此时路由表"+r2.getTableName()+"的目的网络"+r.getNetto()+"距离为"+r.getDistance()+"为不可达");
                r2.print();
                return;
            }
        }
        HashSet<String> set = new HashSet<String>();
        for (Rip rip : r1.getRips()) {
            set.add(rip.getNetto());//将目的网络加入set表 下面用contain方法判断是否包含
        }
        for (Rip rip : r2.getRips()) {
            rip.setDistance(rip.getDistance() + 1);//将距离+1
            rip.setNext(r2.getTableName());//将r2的下一跳全改为r2的表名
        }
        for (Rip j : r2.getRips()) {//遍历r2路由表
            if (!set.contains(j.getNetto()))//set中不包含的情况
            {
                r1.getRips().add(j);//1、若原路由表没有 RIP 中的目的网络,直接添加到原路由表中
            } else {//2、若原路由表中有 RIP 中的目的网络 N
                for (Rip i : r1.getRips()) {
                    if (i.getNetto().equals(j.getNetto())) {//取到相同的目的网络的位置
                        if (!i.getNext().equals(j.getNext())) {// 但下一跳地址不是 X ,选择跳数少的替换。如果两者跳数一样,则保留原路由表的项
                            if (j.getDistance() < i.getDistance()) {//只有当r2的跳数小于r1时才替换
                                i.setDistance(j.getDistance());//替换跳数
                                i.setNext(j.getNext());//替换下一跳
                            }
                        } else {
                            i.setDistance(j.getDistance());//替换跳数
                            i.setNext(j.getNext());//替换下一跳
                        }
                    }
                }
            }
        }
        Collections.sort(r1.getRips(), new Comparator<Rip>() {//定制排序
            @Override
            public int compare(Rip o1, Rip o2) {
                // TODO Auto-generated method stub
                return o1.getNumber()-o2.getNumber();
            }
        });
        updateTable2(r2,r1);
    }
}

3.5.测试类

public class test extends UpdateTable_qs1 {
    public static void main(String[] args) {
        RipTable ripTable = new RipTable("B");
        RipTable ripTable1 = new RipTable("C");
        Scanner sc = new Scanner(System.in);
        int times = 2, a;
        while (times > 0) {
            ripTable.clear();
            ripTable1.clear();
           //第一组数据
           //  Rip rip=new Rip("N1",7,"A"); ripTable.getRips().add(rip);
           //  Rip rip1=new Rip("N2",2,"C");ripTable.getRips().add(rip1);
           //  Rip rip2=new Rip("N6",8,"F");ripTable.getRips().add(rip2);
           //  Rip rip3=new Rip("N8",4,"E");ripTable.getRips().add(rip3);
           //  Rip rip4=new Rip("N9",4,"D");ripTable.getRips().add(rip4);
           //  Rip rip5=new Rip("N2",15); ripTable1.getRips().add(rip5);
           //  Rip rip6=new Rip("N3",2);ripTable1.getRips().add(rip6);
           //  Rip rip7=new Rip("N4",8);ripTable1.getRips().add(rip7);
           //  Rip rip8=new Rip("N8",2);ripTable1.getRips().add(rip8);
           //  Rip rip9=new Rip("N7",4);ripTable1.getRips().add(rip9);
            //第二组数据
            Rip rip = new Rip("N1", 5, "A");ripTable.getRips().add(rip);
            Rip rip1 = new Rip("N2", 3, "C");ripTable.getRips().add(rip1);
            Rip rip2 = new Rip("N6", 6, "F");ripTable.getRips().add(rip2);
            Rip rip3 = new Rip("N8", 4, "E");ripTable.getRips().add(rip3);
            Rip rip5 = new Rip("N1", 5);ripTable1.getRips().add(rip5);
            Rip rip6 = new Rip("N2", 4);ripTable1.getRips().add(rip6);
            Rip rip7 = new Rip("N3", 8);ripTable1.getRips().add(rip7);
            Rip rip8 = new Rip("N6", 4);ripTable1.getRips().add(rip8);
            Rip rip9 = new Rip("N8", 3);ripTable1.getRips().add(rip9);
            ripTable.print();
            ripTable1.print();
            System.out.println("请输入要模拟的功能");
            System.out.println("1.更新一次路由表");
            System.out.println("2.好消息传的快,坏消息传得慢");
            System.out.println("3.按照时间更新路由表");//这个没有写! 逻辑和2差不多
            a = sc.nextInt();
            switch (a) {
                case 1:
                    updateTable(ripTable, ripTable1);
                    times--;
                    break;
                case 2:
                    updateTable2(ripTable,ripTable1);
                    times--;
                    break;
            }
        }
    }
}

3.5.运行截图

在这里插入图片描述
总结: 关于要求三,把要求二的代码稍微改改,把逻辑改成当跳数为16时,设置为不可达,当所有都为不可达时,也可以视为稳定状态hhh。
实验也查完了, 上面的代码rip算法的逻辑应该是没有问题的,注解也有。如果要拷贝的话,可以根据自己的需求修改一下。

猜你喜欢

转载自blog.csdn.net/qq374461948/article/details/106053437
今日推荐