RIP的算法思想:
(1)收到相邻路由器(其地址为X)的一个RIP报文,先修改此RIP报文中的所有项目:将“下一跳”字段中的地址都改为X,并将所有的“距离”字段的值加1。
(2)对修改后的RIP报文中的每一个项目,重复以下步骤:
若项目中的目的网络不在路由表中,则将该项目添加到路由表中。
否则
若下一跳字段给出的路由器地址是同样的,则将收到的项目替换原路由表中的项目。
否则
若收到的项目中的距离小于路由表中的距离,则进行更新,
否则,什么也不做
(3)若3分钟还没有收到相邻路由器的更新路由表,则将此相邻路由器记为不可达的路由器,即将距离置为16(距离为16表示不可达)
(4)返回。
**
实验部分截图如下:
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 ripTableList = new ArrayList();//将表用List储存起来
public String getTableName() {
return tableName;
}
public void setTableName(String tableName) {
this.tableName = tableName;
}
public List 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 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();
}
}
如有疑问欢迎咨询[email protected]