Java模拟路由协议-rip(路由器仿真实验)

前言:

好久不见,有段时间没有写文章了,本篇文章,由Blue我带大家来复现rip协议。我们以

b站湖南教师匠所讲rip的视频中的例子为我这篇文章所模拟的路由路径

如图:

模拟路径

视频:http://【深入浅出计算机网络 - 4.4.3 路由信息协议RIP】https://www.bilibili.com/video/BV1ST411K7nK?vd_source=bb412cc25ca27e171f8e17085daad038

Rip协议工作原理:

  • 1、rip协议要求网络中每个路由器都要维护从它自己到其他每一个目的网络的距离记录。
  • 2、rip认为好的路由就是它通过的网路数目少的,及"距离最短"。
  • 3、rip最多允许一条路径包括15个网络。距离为16时相当于不可达。
  • 4、仅和相邻路由器交换信息,这里的信息指的是所有网络的最短距离,以及到每个网络应经过的下一跳路由
  • 5、按固定时间间隔交换路由信息

代码实现:

第一步:搭建项目

注意 :我搭建的是boot项目,实际我这个复现,并没使用boot,所以你也可以不搭建boot

项目结构:

第二步:定义路由表中的关键列(目的网络,距离,下一跳)

RouterTable:

java 复制代码
package com.example.Kclass;

/**
 * 路由表:
 * 1、目的网络
 * 2、距离
 * 3、下一跳路由器
 */
public class RouterTable implements Cloneable{
    private Integer AimNet;
    private Integer distance;
    private String NextRouter;


    public RouterTable() {
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    public RouterTable(Integer AimNet, Integer distance, String NextRouter) {
        this.AimNet = AimNet;
        this.distance = distance;
        this.NextRouter = NextRouter;
    }

    /**
     * 获取
     * @return AimNet
     */
    public Integer getAimNet() {
        return AimNet;
    }

    /**
     * 设置
     * @param AimNet
     */
    public void setAimNet(Integer AimNet) {
        this.AimNet = AimNet;
    }

    /**
     * 获取
     * @return distance
     */
    public Integer getDistance() {
        return distance;
    }

    /**
     * 设置
     * @param distance
     */
    public void setDistance(Integer distance) {
        this.distance = distance;
    }

    /**
     * 获取
     * @return NextRouter
     */
    public String getNextRouter() {
        return NextRouter;
    }

    /**
     * 设置
     * @param NextRouter
     */
    public void setNextRouter(String NextRouter) {
        this.NextRouter = NextRouter;
    }

    public String toString() {
        return "RouterTable{AimNet = " + AimNet + ", distance = " + distance + ", NextRouter = " + NextRouter + "}";
    }
}

第三步:定义路由器

Router:

java 复制代码
package com.example.Kclass;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 路由器的模板类
 *
 */
public class Router {
   private int id;
   List<RouterTable> routerTables = new ArrayList<>();

    public void setId(int id) {
        this.id = id;
    }

    public int getId() {
        return id;
    }


   public String find(int aimid){
        String sc ="完成";
        for (RouterTable e : routerTables){
            if(e.getAimNet()==aimid){
                System.out.println("需要经过的路由器:"+this.id);
                System.out.println("");
                if(e.getNextRouter().equals("直连")){
                    return sc;
                }else {
                    return e.getNextRouter();
                }
            }
        }
       return sc;
   }



    //添加操作
    public  void add(RouterTable routerTable){
        int count=0;
        //存在相同的目的网络则不添加
        for (RouterTable e1  : routerTables){
            if(e1.getAimNet().equals(routerTable.getAimNet())){
                //不添加
                return;
            }
        }
        routerTables.add(routerTable);
    }

    //更新操作
    public void update(List<RouterTable> r1){
        /**
         * 遍历,看这个路由表满足这几种可能不?
         * 1、没有就插入
         * 2、有,如果下一跳相同则直接更新
         * 3、有,下一跳不同,且r1的距离小于自身的,将下一跳换成r1的下一跳,并且更新
         * 4、有,下一跳不同,且r1的距离大于自身的,不管舍弃
         */
        //遍历
        for (int i=0;i<r1.size();i++){
            for (int j=0;j<routerTables.size();j++){
                //是否存在相同的目的网络
                if(r1.get(i).getAimNet().equals(routerTables.get(j).getAimNet())){
                    //是否下一跳也相同
                    if(r1.get(i).getNextRouter().equals(routerTables.get(j).getNextRouter())){
                        //相同,直接更新
                        routerTables.get(j).setDistance(r1.get(i).getDistance());
                        break;
                    }else {
                        //不同,判断距离
                        if(routerTables.get(j).getDistance()>r1.get(i).getDistance()){
                            routerTables.get(j).setDistance(r1.get(i).getDistance());
                            break;
                        }else {
                            break;
                        }
                    }
                }
                if(j==routerTables.size()-1){
                    routerTables.add(r1.get(i));
                }
            }
        }
    }
    //打印其路由表
    public void prints(){
        System.out.println(id+"的路由表为:");
        System.out.println("---目的网络---距离-----下一跳路由-----");
        for(RouterTable e : routerTables){
            System.out.println("---"+e.getAimNet()+"-----"+e.getDistance()+"------"+e.getNextRouter());
            System.out.println("");
        }
    }
    public  List<RouterTable> deepCopyRouterTables() {
        List<RouterTable> copiedList = new ArrayList<>(routerTables.size());
        for (RouterTable routerTable : routerTables) {
            try {
                copiedList.add((RouterTable) routerTable.clone()); // 深拷贝
            } catch (CloneNotSupportedException e) {
                e.printStackTrace(); // 处理异常
            }
        }
        return copiedList;
    }
}

第四步:定义网络

复制代码
NetWork:
java 复制代码
package com.example.Kclass;

public class NetWork {
    private int id;

    public NetWork() {
    }

    public NetWork(int id) {
        this.id = id;
    }

    /**
     * 获取
     * @return id
     */
    public int getId() {
        return id;
    }

    /**
     * 设置
     * @param id
     */
    public void setId(int id) {
        this.id = id;
    }

    public String toString() {
        return "NetWork{id = " + id + "}";
    }
}

第五步:定义User

java 复制代码
package com.example.Kclass;

public class User {
     private int id ;
     private int Routid;


    public User() {
    }

    public User(int id, int Routid) {
        this.id = id;
        this.Routid = Routid;
    }

    /**
     * 获取
     * @return id
     */
    public int getId() {
        return id;
    }

    /**
     * 设置
     * @param id
     */
    public void setId(int id) {
        this.id = id;
    }

    /**
     * 获取
     * @return Routid
     */
    public int getRoutid() {
        return Routid;
    }

    /**
     * 设置
     * @param Routid
     */
    public void setRoutid(int Routid) {
        this.Routid = Routid;
    }

    public String toString() {
        return "User{id = " + id + ", Routid = " + Routid + "}";
    }
}

第六步:Ts代码

java 复制代码
package com.example.test;

import com.example.Kclass.NetWork;
import com.example.Kclass.Router;
import com.example.Kclass.RouterTable;
import com.example.Kclass.User;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.CountDownLatch;

/**
 * 1、四个网络
 * 2、四个路由器
 * 3、创建图(利用图来表示链接)
 * 4、该类目的是弄好路由器的交换表
 */
public class Ts {
    public static void main(String[] args) {

        List<NetWork> netWorks =new ArrayList<>();
        List<Router> routers =new ArrayList<>();
        rip(netWorks,routers);
        //用户界面
        User user =new User(1,1);
        MainPannel(routers,user);

    }
    public static void ppt(List<Router> routers){
        for (Router e:routers){
            e.prints();
        }
    }

    public static void MainPannel(List<Router> routers,User user){
        while (true){
            int a;
            System.out.println("选项1:打印所有路由表");
            System.out.println("选项2:用户传输信息");
            System.out.println("选项3:退出");
            Scanner s =new Scanner(System.in);
            System.out.println("请输入选项:");
            a=s.nextInt();
            switch (a){
                case 1:
                    ppt(routers);
                    break;
                case 2:
                    userprint(routers,user);
                    break;
                case 3:
                    return;
            }
        }
    }

    public static void userprint(List<Router> routers, User user){
        System.out.println("请输入需要传送到的网络");
        int a;
        Scanner sc = new Scanner(System.in);
        a=sc.nextInt();
        int t=a;
        //知道自己从那个路由出发
       int routid= user.getRoutid();
        Router router = routers.get(routid - 1);
        boolean flage =true;
        while (flage){
            String s = router.find(t);
            if(s.equals("完成")){
                System.out.println("完成");
                return;
            }
            a = Integer.parseInt(s);
            router=routers.get(a-1);
        }
    }

    public static void rip( List<NetWork> netWorks, List<Router> routers) {
        //生成四个网络
        //令四个网络为1,2,3,4

        for (int i=1;i<=4;i++){
            NetWork e =new NetWork();
            e.setId(i);
            netWorks.add(e);
        }
        //生成四个路由器
        //令四个路由器为5,6,7,8

        for (int i=5;i<=8;i++){
            Router e =new Router();
            e.setId(i-4);
            routers.add(e);
        }
        //生成线路
        int[][] arry=CreateImage();
        //rip基本原理规定:路由器刚开始工作只知道自己到直连网络的距离为1
        //根据线路初始化
        initialization(routers,arry);
        //打印初始化后的每个路由器的路由表
//        System.out.println("--------------------路由表的初始化-----------------------");
//        for (Router e:routers){
//            e.prints();
//        }
        //根据rip基本原理每个路由器仅和相邻路由器周期性地交换并更新路由信息
        find(routers,arry);
//        System.out.println("--------------------路由表的最终-----------------------");
//        for (Router e:routers){
//            e.prints();
//        }
    }


    public static int[][] CreateImage(){
        int[][] arry={
                {0,0,0,0,1,1,0,0},//N1所对应的行,0
                {0,0,0,0,1,0,1,0},//N2所对应的行,1
                {0,0,0,0,0,0,1,1},//N3所对应的行,2
                {0,0,0,0,0,1,1,1},//N4所对应的行,3
                {1,1,0,0,0,0,0,0},//R1所对应的行,4
                {1,0,0,1,0,0,0,0},//R2所对应的行,5
                {0,1,1,1,0,0,0,0},//R3所对应的行,6
                {0,0,1,1,0,0,0,0} //R4所对应的行,7
        };
        return arry;
    }

    //初始化
    public static void initialization(List<Router> routers,int[][] arry){
        for (int i=4;i<=7;i++){
            for (int j=0;j<4;j++){
                if(arry[i][j]==0){
                    continue;
                }
                if(arry[i][j]==1){
                    routers.get(i-4).add(new RouterTable(j+1,1,"直连"));
                }
            }
        }
    }

    //用于更新
    public static void exchenge(Router e1,Router e2){
      //先让e1去更新e2
        // 深拷贝
        List<RouterTable> Copye2 = e2.deepCopyRouterTables();
        String next=e2.getId()+"";

        //根据rip协议,让其距离加1,下一跳变为e1
        for (RouterTable table :Copye2){
            table.setDistance(table.getDistance()+1);
            table.setNextRouter(next);
        }
        e1.update(Copye2);

        //e2去更新e1
        String next2=e1.getId()+"";
        //深拷贝
        List<RouterTable> copy1 = e1.deepCopyRouterTables();
        //根据rip协议,让其距离加1,下一跳变为e2
        for (RouterTable table :copy1){
            table.setDistance(table.getDistance()+1);
            table.setNextRouter(next2);
        }
        e2.update(copy1);
    }

    //用于遍历数组,查找相同路由器
    public static void find(List<Router> routers,int[][] arry){
        //双指针遍历
        int A=0;
        int B=0;
        for (int i=0;i<4;i++){
            boolean flage=true;
            //优化操作
            if(flage) {
                for (int j = 4; j < 8; j++) {
                    if (arry[i][j] == 1) {
                        A = j;//找到第一个1,然后继续下去找
                        B=j;
                         flage=false;
                         break;
                    }
                }
            }

            for (int j=B+1;j<8;j++){
                if (arry[i][j]==1)
                {
                    //执行更新
                    exchenge(routers.get(A-4),routers.get(j-4));
                    //判断是否还有可能存在相邻
                    if(j<7){
                        int s=B;
                        B=j;
                        for (int w=B+1;w<8;w++){
                            if(arry[i][w]==1){
                                exchenge(routers.get(A-4),routers.get(w-4));
                                exchenge(routers.get(s-4),routers.get(w-4));
                            }else {
                                break;
                            }
                        }
                    }
                }
            }

        }
    }

}

实现效果:

主页面:

选项1:

选项2:

选项3:

结语:

你好,我是Blue. 为帮助别人少走弯路而写博客 !!!

如果本篇文章帮到了你 不妨点个赞吧~ 我会很高兴的 😄 (^ ~ ^) 。想看更多 那就点个关注吧 我会尽力带来有趣的内容 😎。

如果你遇到了问题,自己没法解决,可以私信问我。

感谢订阅专栏 三连文章!!

相关推荐
sinat_26229211几秒前
Java面试实战:电商场景下的Spring Cloud微服务架构与缓存技术剖析
java·redis·spring cloud·微服务·消息队列·缓存技术·监控运维
大阔几秒前
安卓开发中XML布局的实用技巧 —— 移动应用开发(安卓)
java
用户484695206971 分钟前
ArrayList 源码分析
java
大阔2 分钟前
如何使用Intent在安卓Activity间传输数据 —— 移动应用开发(安卓)
java
AronTing3 分钟前
缓存与数据库一致性深度解析与解决方案
java·后端·面试
AronTing4 分钟前
分布式缓存与本地缓存协同优化实践
java·后端·面试
带刺的坐椅7 分钟前
Java AI(智能体)编排开发就用 Solon Flow
java·ai·openai·solon·solon-flow
编码七号14 分钟前
【axios取消请求】如何在token过期后取消未响应的请求
java·前端·javascript
落笔画忧愁e16 分钟前
数据通信学习笔记之OSPF的区域
笔记·学习·智能路由器