Hi
This the final project that i submitted.
It might be having some improper documentation and some bad usage of Java.
As this project runs on local system, instead of using different IP address and same port number, i am doing it other way.
NetworkBoot.java provides the initial neighbor details to each router.
Thanks
-Sunny Jain
enter code here
/*
* File Name : Router.java
* Public Class Name : Router
*
*/
//~--- JDK imports ------------------------------------------------------------
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.LinkedBlockingQueue;
import javax.swing.SwingUtilities;
/**
*
* NA1 project 2 spring 2009 semester
* @author sunny jain
*
*
*/
public class Router extends Thread {
/**
* HashMap containing list of neighbors and cost to reach them.
*/
private HashMap<Integer, Integer> hmapDirectNeighbours = new HashMap<Integer, Integer>(61);
/**
* HashMap containing list of destination as key and routing info to them as value.
* Routing info contains RouteDetail object.
* @see RouteDetail
*/
private HashMap<Integer, RouteDetail> hmapRoutes = new HashMap<Integer, RouteDetail>();
/**
* DatagramSocket
*/
private DatagramSocket dSoc;
/**
* DatagramPacket
*/
private DatagramPacket dpackReceive, dpackSend;
/**
* Inetaddress of system on which runs this algorithm.
*/
private InetAddress localAddress;
/**
* port to listen at for incoming route info from neighbors.
*/
int port;
private LinkedBlockingQueue<DatagramPacket> lbq = new LinkedBlockingQueue<DatagramPacket>();
/**
* Made constructor private to force initialization by specifying port
* compulsory.
*/
private Router() {
}
/**
* Constuctor taking port number as parameter and creates a datagramSocket
* to listen for incoming DatagramPacket on that socket.
* @param port
*/
public Router(int port) {
try {
this.port = port;
localAddress = InetAddress.getByName("127.0.0.1");
dSoc = new DatagramSocket(port, localAddress);
} catch (Exception ex) {
System.out.println("Error while creating socket : " + ex.getMessage());
}
this.start();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
while (true) {
try {
received_Route_Info(lbq.take());
} catch (InterruptedException ex) {
System.out.println("Error while reading elements from datagram queue");
}}}});
}
public void setRouterBootInfo(String strNeighboursInfo) {
String[] strNeighbouringNodes = strNeighboursInfo.split(";");
for (int i = 0; i < strNeighbouringNodes.length; i++) {
String[] strNodeIpAndPort = strNeighbouringNodes[i].split(":");
hmapDirectNeighbours.put(Integer.valueOf(strNodeIpAndPort[0]), Integer.valueOf(strNodeIpAndPort[1]));
hmapRoutes.put(Integer.valueOf(strNodeIpAndPort[0]), new RouteDetail(null, Integer.valueOf(strNodeIpAndPort[1])));
}
propagateChanges();
// entry in Route table....No need for infinity as we creat entry when a node is reachable.
}
@Override
public void run() {
while (true) {
try {
byte[] buf = new byte[250];
// receive request
dpackReceive = new DatagramPacket(buf, buf.length);
dSoc.receive(dpackReceive);
lbq.put(dpackReceive);
} catch (InterruptedException ex) {
ex.printStackTrace();
dSoc.close();
} catch (IOException e) {
e.printStackTrace();
dSoc.close();
}
}
}
/**
* This method is called for each DatagramPacket received containing new
* routing information.
*
* This method checks whether this packet came from neighboring node
* (routers) only. If true it applies Distance vector algorithm on data
* present in datagram packet and due to this information if their is any
* change in local routing information that it displays current local
* updated routing information and also sends this updated information to
* other neighbours only.
*
* @param dataPckt
* @see #validate_Is_Packet_From_Neighbor(java.net.DatagramPacket)
* @see #apply_Routing_Algorithm(java.net.DatagramPacket, java.util.HashMap)
* @see #print_route_info()
* @see #send_Updates_To_Neighbors(routesInfo)
*/
private void received_Route_Info(DatagramPacket dataPckt) {
if (dataPckt.getPort() == 4000) {
setRouterBootInfo(getStringFromBytes(dataPckt));
} else if (validate_Is_Packet_From_Neighbor(dataPckt)) {
if (apply_Routing_Algorithm(dataPckt, create_HashMap_Routes(getStringFromBytes(dataPckt)))) {
// if their is change in routing information.
propagateChanges();
}
}
}
/**
* Validates whether the Datagram packet received is from the neighbors only.
* @param datagrampckt DatagramPacket comtaining routing information.
* @return true if datagrampckt is from neighbors only otherwise false.
*/
private boolean validate_Is_Packet_From_Neighbor(DatagramPacket datagrampckt) {
return hmapDirectNeighbours.containsKey(Integer.valueOf(datagrampckt.getPort()));
}
/**
* Returns byte representaion of data contained in DatagramPacket pkt.
* @param pkt DatagramPacket
* @return byte representation of data contained in pkt
*/
private String getStringFromBytes(DatagramPacket pkt) {
String strData = new String(pkt.getData());
return strData.substring(0, strData.lastIndexOf(';'));
}
/**
* Applies Distance Vector algorithm using newly received routing information
* and information presently with this node (Router).
* @param datagrampckt DatagramPacket containing routing information.
* @param newRoutes HashMap of routes new information received with
* destination as key and cost to that destination as value.
*/
private boolean apply_Routing_Algorithm(DatagramPacket dataPckt, HashMap<Integer, Integer> newRoutes) {
boolean updated = false;
Integer pktSourse = Integer.valueOf(dataPckt.getPort());
// Get a set of the routes
Set<Integer> set = newRoutes.keySet();
// Get an iterator
Iterator<Integer> iterator = set.iterator();
// Display elements.
while (iterator.hasNext()) {
Integer key = iterator.next();
Integer nextHopCost = hmapRoutes.get(pktSourse).getPathCost();
int optionalCost = newRoutes.get(key) + (nextHopCost == null ? 0 : nextHopCost);
if (hmapRoutes.containsKey(key)) {
RouteDetail routeDetail = hmapRoutes.get(key);
if (routeDetail.getPathCost().compareTo(optionalCost) > 0) {
routeDetail.setNextHop(pktSourse);
routeDetail.setPathCost(optionalCost);
hmapRoutes.put(key, routeDetail);
updated = true;
// try to verify above statement
}
} else {
if (!key.equals(port)) {
RouteDetail newRouteDetail = new RouteDetail(pktSourse, optionalCost);
hmapRoutes.put(key, newRouteDetail);
updated = true;
}
}
}
return updated;
}
/**
* When internal routing information is chaged, send this information to
* other neighbors.
* @param routesInfo byte representaion of routing information.
*/
private void send_Updates_To_Neighbors(byte[] routesInfo) {
// Get a set of the routes
Set<Integer> set = hmapDirectNeighbours.keySet();
// Get an iterator
Iterator<Integer> iterator = set.iterator();
// Display elements.
while (iterator.hasNext()) {
dpackSend = new DatagramPacket(routesInfo, routesInfo.length, localAddress, iterator.next().intValue());
try {
dSoc.send(dpackSend);
} catch (IOException ex) {
System.out.println("Error while sending route updates : " + ex.getMessage());
}
}
}
/**
* Parses routeInfo to creat an HashMap based on this informationin the
* format as HashMap of <<Integer:Destination>,<Integer: Cost to this destination>>
* @param routeInfo contains routing information as String in the syntax
* of {<Destination>:<Cost to destination>;}
* @return Hashmap<<Integer:Destination>,<Integer: Cost to this destination>>
*/
private HashMap<Integer, Integer> create_HashMap_Routes(String routeInfo) {
HashMap<Integer, Integer> routes = new HashMap<Integer, Integer>();
String[] straRoute = routeInfo.split(";");
for (int i = 0; i < straRoute.length; i++) {
String[] straDestAndCost = straRoute[i].split(":");
routes.put(Integer.parseInt(straDestAndCost[0]), Integer.parseInt(straDestAndCost[1]));
}
return routes;
}
/**
* Converts current routing information stored as HashMap to String
* presentation in format as {<Destination>:<Cost to destination>;}
*
* @return String representaion of routing information.
* @see #hmapRoutes.
*/
private String create_String_Of_Routes() {
StringBuilder strB = new StringBuilder();
// Get a set of the routes
Set<Integer> set = hmapRoutes.keySet();
// Get an iterator
Iterator<Integer> iterator = set.iterator();
// Display elements.
while (iterator.hasNext()) {
Integer destination = iterator.next();
strB.append(destination);
strB.append(":");
strB.append(hmapRoutes.get(destination).getPathCost());
strB.append(";");
}
return strB.toString();
}
/**
* Prints the current routing information stored in <code>hmapRoutes</code>
* to default output stream of this program.
* @see #hmapRoutes.
*/
public void print_route_info() {
RouteDetail route;
StringBuilder builder;
// PRINT THE CURRENT ROUTING INFO AT THIS NODE
System.out.println("");
System.out.println(" TABLE AT NODE WITH PORT : " + port);
System.out.println("--------------------------------------------------------------------------------");
System.out.println("\t\tTo \t|\t Via\t|\tCost\t\t");
System.out.println("--------------------------------------------------------------------------------");
// Get a set of the routes
Set<Integer> set = hmapRoutes.keySet();
// Get an iterator
Iterator<Integer> iterator = set.iterator();
// Display elements.
while (iterator.hasNext()) {
Integer key = iterator.next();
route = hmapRoutes.get(key);
builder = new StringBuilder();
builder.append("\t\t" + key.intValue());
builder.append("\t|\t" + (route.getNextHop() == null ? " -" : route.getNextHop()));
builder.append("\t|\t" + route.getPathCost() + "\t\t");
System.out.println(builder.toString());
}
}
/**
* This class provides details for each destination.
* It provides detail of cost that will be incurred to reach that
* destination and next router on that path.
*/
private class RouteDetail {
Integer nextHop;
Integer pathCost;
public RouteDetail(Integer nextHop, Integer pathCost) {
this.nextHop = nextHop;
this.pathCost = pathCost;
}
public Integer getNextHop() {
return nextHop;
}
public void setNextHop(Integer nextHop) {
this.nextHop = nextHop;
}
public Integer getPathCost() {
return pathCost;
}
public void setPathCost(Integer pathCost) {
this.pathCost = pathCost;
}
}
private void propagateChanges() {
print_route_info();
send_Updates_To_Neighbors(create_String_Of_Routes().getBytes());
}
public static void main(String[] args) {
new Router(Integer.parseInt(args[0]));
}
}
/*
* File Name : NetworkBoot.java
* Public Class Name : NetworkBoot
*
*/
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
/**
*
* NA1 project 2 spring 2009 semester
* @author sunny jain
*
*
*/
public class NetworkBoot {
public static void main(String[] args) {
try {
DatagramSocket dSoc = new DatagramSocket(4000, InetAddress.getByName("127.0.0.1"));
String[] sendD = {"4006:3;4007:5;4009:2;", "4005:3;4007:3;4008:6;", "4005:5;4006:3;", "4009:2;4006:6;", "4008:2;4005:2;"};
for (int i = 0, port = 4005; i < 5; i++) {
dSoc.send(new DatagramPacket(sendD[i].getBytes(), sendD[i].length(), InetAddress.getByName("127.0.0.1"), port++));
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}