RIP的算法思想:
(1)收到相邻路由器(其地址为X)的一个RIP报文,先修改此RIP报文中的所有项目:将“下一跳”字段中的地址都改为X,并将所有的“距离”字段的值加1。
(2)对修改后的RIP报文中的每一个项目,重复以下步骤:
若项目中的目的网络不在路由表中,则将该项目添加到路由表中。
否则
若下一跳字段给出的路由器地址是同样的,则将收到的项目替换原路由表中的项目。
否则
若收到的项目中的距离小于路由表中的距离,则进行更新,
否则,什么也不做
(3)若3分钟还没有收到相邻路由器的更新路由表,则将此相邻路由器记为不可达的路由器,即将距离置为16(距离为16表示不可达)
(4)返回。
**
实验部分截图如下:

rip模拟python_System


rip模拟python_Line_02

废话少说直接上源代码(本代码发送数据为了方便用的是UDP,读者可以将其改为更为安全的TCP)*

RipLine类封装了路由表的三个基本信息即(目的网络地址,距离,下一跳)

public class RipLine {
    //表结构
    private String ripnet;//目的网络地址
    private String ripnext;//距离
    private int ripdistance;//下一跳

    public String getRipnet() {
        return ripnet;
    }

    public String getRipnext() {
        return ripnext;
    }

    public int getRipdistance() {
        return ripdistance;
    }

    public void setRipnet(String ripnet) {
        this.ripnet = ripnet;
    }

    public void setRipnext(String ripnext) {
        this.ripnext = ripnext;
    }

    public void setRipdistance(int ripdistance) {
        this.ripdistance = ripdistance;
    }

}

类RipTable在类RipLine的基础上加上了表名称进一步封装了路由表,并且将表结构用List储存起来,方便后续操作

import java.util.ArrayList;
import java.util.List;

public class RipTable {
    private String tableName;//表名称
    private List<RipLine> ripTableList = new ArrayList<RipLine>();//将表用List储存起来

    public String getTableName() {
        return tableName;
    }

    public void setTableName(String tableName) {
        this.tableName = tableName;
    }

    public List<RipLine> getRipTableList() {
        return ripTableList;
    }


    public void addRipTableList(RipLine ripTableLists) {
        ripTableList.add(ripTableLists);
    }

}

类Controller是核心类,它里面封装了Rip协议用到的各种算法,方法里面都有相应的注释

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Scanner;

///控制层
public class Controller {
    //比较连个表的目的路由地址
    public static int IndexTables(RipLine ripLine1, RipTable s_table) {
        int flag = -1;
        for (int i = 0; i < s_table.getRipTableList().size(); i++) {
            if (ripLine1.getRipnet().equals(s_table.getRipTableList().get(i).getRipnet())) {
                flag = i;
                break;
            }

        }
        return flag;
    }
    //复制一个副本
    public static RipTable CopyRip(RipTable stable){
        RipTable copytable=new RipTable();
        copytable.setTableName(stable.getTableName());
        RipLine ripLines=null;
        for (int i=0;i<stable.getRipTableList().size();i++)
        {
            ripLines=new RipLine();
            ripLines.setRipnet(stable.getRipTableList().get(i).getRipnet());
            ripLines.setRipdistance(stable.getRipTableList().get(i).getRipdistance());
            ripLines.setRipnext(stable.getRipTableList().get(i).getRipnext());
            copytable.addRipTableList(ripLines);
        }
        return copytable;
    }
    public static RipTable CompareRip(RipTable s_table, RipTable c_table) {

        int index = 0;

        for (int i = 0; i < c_table.getRipTableList().size(); i++) {
            //目的网络不相等需要加进去
            index = IndexTables(c_table.getRipTableList().get(i), s_table);
            if (index == -1) {
                System.out.println("第" + i + "目的网络不相同");
                s_table.addRipTableList(c_table.getRipTableList().get(i));

            } else {//目的网络相等情况下,比较下一跳是否相等

                if (c_table.getRipTableList().get(i).getRipnext().equals(s_table.getRipTableList().get(index).getRipnext())) {
                    System.out.println("下一跳相同");
                    s_table.getRipTableList().get(index).setRipnet(c_table.getRipTableList().get(i).getRipnet());
                    s_table.getRipTableList().get(index).setRipdistance(c_table.getRipTableList().get(i).getRipdistance());
                    s_table.getRipTableList().get(index).setRipnext(c_table.getRipTableList().get(i).getRipnext());
                } else {

                    if (c_table.getRipTableList().get(i).getRipdistance() < s_table.getRipTableList().get(index).getRipdistance()) {
                        //替换小的
                        System.out.println("替换小的");
                        s_table.getRipTableList().get(index).setRipnet(c_table.getRipTableList().get(i).getRipnet());
                        s_table.getRipTableList().get(index).setRipdistance(c_table.getRipTableList().get(i).getRipdistance());
                        s_table.getRipTableList().get(index).setRipnext(c_table.getRipTableList().get(i).getRipnext());
                    }

                }

            }
        }

        return s_table;
    }

    //修改路由距离加一
    public static RipTable ModifyRip(RipTable table1) {

        RipTable m_table = new RipTable();
        RipLine m_ripLine = new RipLine();
        m_table.setTableName(table1.getTableName());
        for (int i = 0; i < table1.getRipTableList().size(); i++) {

            m_ripLine.setRipnet(table1.getRipTableList().get(i).getRipnet());
            m_ripLine.setRipdistance(table1.getRipTableList().get(i).getRipdistance() + 1);
            //  m_ripLine.setRipnext(table1.getRipTableList().get(i).getRipnext());
            m_ripLine.setRipnext(table1.getTableName());
            m_table.addRipTableList(m_ripLine);

            m_ripLine = new RipLine();

        }

        return m_table;
    }

    //分割成字符串
    public static String EncodeData(RipTable table) {

        List<RipLine> ripLines = table.getRipTableList();
        String strs = "";
        strs += table.getTableName();
        strs += "#";
        for (int i = 0; i < ripLines.size(); i++) {

            strs += ripLines.get(i).getRipnet();
            strs += "@";
            strs += ripLines.get(i).getRipdistance();
            strs += "@";
            strs += ripLines.get(i).getRipnext();
            strs += "$";

        }

        return strs;
    }

    //将字符合并成RipTable表
    public static RipTable mergeData(String str) {
        RipTable ripTable = new RipTable();
        RipLine ripLine = new RipLine();
        int times = 0;
        String temp = "";
        for (int i = 0; i < str.length(); i++) {
            if (str.charAt(i) == '#' && times == 0) {
                ripTable.setTableName(temp);
                temp = "";
                times++;
            } else if (str.charAt(i) == '@' && times == 1) {
                ripLine.setRipnet(temp);
                temp = "";
                times++;
            } else if (str.charAt(i) == '@' && times == 2) {
                ripLine.setRipdistance(Integer.parseInt(temp));
                times++;
                temp = "";
            } else if (str.charAt(i) == '$' && times == 3) {
                ripLine.setRipnext(temp);
                temp = "";
                times++;
                ripTable.addRipTableList(ripLine);
                ripLine = new RipLine();
            } else {
                temp += str.charAt(i);
                if (times == 4) times = 1;
            }
        }
        return ripTable;
    }

    //初始化路由表
    public static RipTable initTable() throws IOException {

        BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
        RipTable table = new RipTable();
        System.out.println("输入表名称");
        Scanner p = new Scanner(System.in);
        table.setTableName(input.readLine());
        RipLine ripLine = null;
        System.out.println("数目");
        int n = p.nextInt();
        for (int i = 0; i < n; i++) {
            ripLine = new RipLine();
            System.out.println("请输入第" + (i + 1) + "条目的地址");
            String temp = input.readLine();
            ripLine.setRipnet(temp);
            System.out.println("请输入第" + (i + 1) + "条距离");
            ripLine.setRipdistance(p.nextInt());
            System.out.println("请输入第" + (i + 1) + "条下一跳");
            ripLine.setRipnext(input.readLine());
            table.addRipTableList(ripLine);

        }

        return table;
    }

    //打印路由表
    public static void showTable(RipTable table) {
        System.out.println("表名称:");
        System.out.println(table.getTableName());
        System.out.println("目的网络-" + "--向量距离---" + "下一跳-----");
        for (int j = 0; j < table.getRipTableList().size(); j++) {
            System.out.println("    " + table.getRipTableList().get(j).getRipnet() + "         " + table.getRipTableList().get(j).getRipdistance() + "           " + table.getRipTableList().get(j).getRipnext());
        }
    }
}

类RipServer负责接收RipClient发过来的路由表,并进行更新操作,也可以发送路由表给RipClient

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class RipServer extends Thread {

    private static DatagramSocket socket;
    private static DatagramPacket packet;
    private static InetAddress address;

    public static void receive(DatagramSocket socket) throws Exception {

        byte[] data = new byte[1024];

        packet = new DatagramPacket(data, data.length);

        socket.receive(packet);

        String info = new String(data, 0, data.length);

        RipTable table = Controller.initTable();
        Controller.showTable(table);

        String temps = Controller.EncodeData(table);
        RipTable table1 = Controller.mergeData(info);
        System.out.println("收到的原路由表信息");
        Controller.showTable(table1);

        RipTable m_table = Controller.ModifyRip(table1);
        System.out.println("距离加一后的路由表信息");
        Controller.showTable(m_table);
        RipTable stable=Controller.CopyRip(table);
        RipTable table2 = Controller.CompareRip(stable, m_table);
        System.out.println("最后跟新后的路由");
        Controller.showTable(table2);
        send(temps, socket, packet);

    }


    public static void send(String temps, DatagramSocket socket, DatagramPacket packet) throws Exception {

        address = packet.getAddress();

        int port = packet.getPort();

        // RipTable table = Controller.initTable();

        // String temps = Controller.EncodeData(table);

        byte[] data2 = temps.getBytes();

        DatagramPacket packet2 = new DatagramPacket(data2, data2.length, address, port);
        socket.send(packet2);

        socket.close();

    }

    public void run() {
        try {
            receive(socket);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws Exception {

        socket = new DatagramSocket(10010);
        new RipServer().start();

    }

}

类RipClient发送路由表给RipServer,同时也可以接收RipServer发过来的路由表,进行更新操作

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class RipClient implements Runnable{
    private static DatagramPacket packet;
    private static DatagramSocket socket;
    private static InetAddress address;
    private static RipTable ripTableClient;//全局用于比较路由信息
    public void run(){
        try {
            recived(socket);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static void send(DatagramSocket socket,DatagramPacket packet)throws Exception{
        address = InetAddress.getByName("127.0.0.1");
        int port = 10010;
        RipTable tabletemp=Controller.initTable();
        ripTableClient = Controller.CopyRip(tabletemp);
        String strs=Controller.EncodeData(tabletemp);
        byte[] data = strs.getBytes();
        packet =new DatagramPacket(data,data.length,address,port);
        socket.send(packet);

    }
    public static void recived(DatagramSocket socket)throws Exception{

        byte[] data2=new byte[1024];

        DatagramPacket packet2 = new DatagramPacket(data2, data2.length);

        socket.receive(packet2);

        String raply = new String(data2, 0, packet2.getLength());

        RipTable table1=Controller.mergeData(raply);
        System.out.println("本机的路由表");
        Controller.showTable(ripTableClient);
        System.out.println("收到的路由表");
        Controller.showTable(table1);

        RipTable tabletemp1=Controller.ModifyRip(table1);
        System.out.println("距离加一");
        Controller.showTable(tabletemp1);
        RipTable tabletemp2 = Controller.CompareRip(ripTableClient, table1);
        System.out.println("最后跟新的路由表");
        Controller.showTable(tabletemp2);
        socket.close();

    }
    public static void main(String[] args) throws Exception{

        socket = new DatagramSocket();
        send(socket,packet);
        new Thread(new RipClient()).start();

    }

}