RIP的算法思想:
(1)收到相鄰路由器(其地址爲X)的一個RIP報文,先修改此RIP報文中的所有項目:將“下一跳”字段中的地址都改爲X,並將所有的“距離”字段的值加1。
(2)對修改後的RIP報文中的每一個項目,重複以下步驟:
若項目中的目的網絡不在路由表中,則將該項目添加到路由表中。
否則
若下一跳字段給出的路由器地址是同樣的,則將收到的項目替換原路由表中的項目。
否則
若收到的項目中的距離小於路由表中的距離,則進行更新,
否則,什麼也不做
(3)若3分鐘還沒有收到相鄰路由器的更新路由表,則將此相鄰路由器記爲不可達的路由器,即將距離置爲16(距離爲16表示不可達)
(4)返回。
**
實驗部分截圖如下:
廢話少說直接上源代碼(本代碼發送數據爲了方便用的是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();
}
}
如有疑問歡迎諮詢[email protected]