2009-05-09 7 views
1

Ich mache meine Aufgabe in Netzwerkarchitektur 1, wo ich ein Entfernungsvektor-Routing an jedem Knoten implementieren muss.Threading für Distanzvektor, der Pakete nicht löscht

An jedem Knoten habe ich einen Thread, der auf eingehende DatagramPacket s lauscht, die Routing-Informationen von benachbarten Knoten nur an einem bestimmten Port enthalten. Wenn ein Datagramm ankommt, verarbeitet der Thread dieses Datagramm, und wenn es Aktualisierungen in seinen internen Routing-Tabellen gibt, dann sendet es seine Routing-Information an alle seine Nachbarn.

Ich versuche es in Java zu tun.

Das Problem, mit dem ich konfrontiert bin, ist, dass, wenn ein Datagramm ankommt, ich es verarbeiten muss. Wenn während dieser Zeit ein anderes Datagramm ankommt, wird es gelöscht, da der Thread gerade Informationen verarbeitet. Das bedeutet, ich habe einen Informationsverlust.

Kann mir jemand dabei helfen?

Ich verwende die übliche Art des Lesens von einem Socket in Java.

DatagramSocket socket = new DatagramSocket(4445, InetAddress.getByName("127.0.0.1")); 
while (true) { 
    try { 
     byte[] buf = new byte[2000]; 

     // receive request 
     DatagramPacket recvRequest = new DatagramPacket(buf, buf.length); 

     socket.receive(recvRequest); 

     //Some process of data in datagram 

    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 

Antwort

0

DatagramSocket socket = neuer DatagramSocket (4445, InetAddress.getByName ("127.0.0.1")); while (true) { try { // Anmerkung final .. letztes Byte [] buf = neues Byte [2000];

// receive request 
    DatagramPacket recvRequest = new DatagramPacket(buf, buf.length); 

    socket.receive(recvRequest); 

    //Some process of data in datagram 
    (new Thread(new Runnable() { 
     public void run() { 
      // do stuff with data in buf 
      ... 
     } 
    })).start(); 

} catch (IOException e) { 
    e.printStackTrace(); 
} 

}

+0

Leistung Hinweis: Es ist sicherlich nicht effizient, einen neuen Thread für jedes Paket zu instanziieren. Wenn Verarbeitungsreihenfolge von Bedeutung ist, verwenden Sie einen Blocking und eine bereits instanziert Verarbeitungsthread-Puffer in einer FIFO-Weise ausgelesen. Wenn Reihenfolge irrelevant ist, verwenden Sie einen Executor. (Und wenn Sie wirklich die Zyklen drücken wollen, sollten Sie diese byte [] Puffer Recycling ..) – alphazero

2

Sie können das empfangene Datagramm in einem Thread verarbeitet werden, so dass der Thread mit dem Socket-Listener neue Datagramme erhalten fortsetzen können.

0

Ich habe dies nicht in Java getan, aber Sie können (oder sollten) mehr als einen gleichzeitigen Datagrammpuffer an den Socket übergeben (entweder mit mehreren Threads, die jeweils die synchrnonous receive Methode aufrufen, oder vorzugsweise mit einem Thread, der eine aufruft asynchrone Empfangsmethode mehr als einmal).

Der Vorteil der Übergabe von mehreren gleichzeitigen Datagrammpuffern an den Socket ist offensichtlich: dh der Socket hat immer noch einen Puffer (in den das nächste Datagramm empfangen werden soll), auch wenn er bereits einen Puffer (mit einem vorherigen Datagramm) gefüllt hat hat diesen Puffer an dich zurückgegeben.

Sie könnten fragen: "In welcher Reihenfolge werden die Puffer an mich zurückgegeben?" und die Antwort darauf lautet: "Es sollte nicht wichtig sein." Wenn die Reihenfolge, in der Sie Datagramme verarbeiten, wichtig ist, sollten die Datagramme selbst eine Sequenznummer enthalten (da Datagramme bei der Weiterleitung über das Netzwerk aus der Reihe geraten können, unabhängig davon, ob Sie mehrere gleichzeitig an den lokalen Socket übergeben haben) eine konsequente Möglichkeit des "gleichzeitigen" Empfangens wird Ihnen nicht in Reihenfolge geliefert).

0

Es sei daran erinnert, UDP verlustbehafteter Transport ist, bei gleichzeitiger Minimierung Paketverlust eine gute Idee ist, sollten Sie nie annehmen, dass Sie jedes Paket erhalten werden, (oder, dass die Pakete ankommen Sie in der Reihenfolge schickte sie)

1

Dies ist das endgültige Projekt, das ich eingereicht habe. Es kann sein, dass eine unpassende Dokumentation und eine schlechte Verwendung von Java vorliegt. Da dieses Projekt auf einem lokalen System läuft, verwende ich keine andere IP-Adresse und dieselbe Portnummer, sondern mache es anders.

NetworkBoot.java stellt jedem Router die anfänglichen Nachbardetails zur Verfügung.

Dank -Sunny Jain

enter code here 

/* * Dateiname: Router.java * Public Class Name: Router * */

// ~ --- JDK Importe -------------------------------------------------- ----------

import java.io.IOException;

importieren java.net.DatagramPacket;

importieren java.net.DatagramSocket;

importieren java.net.InetAddress;

importieren java.util.HashMap;

importieren java.util.Iterator;

importieren java.util.Set;

importieren java.util.concurrent.LinkedBlockingQueue;

importieren javax.swing.SwingUtilities;

/** * * NA1 Projekt 2 Frühjahr 2009 Semester * @author Sunny Jain * * */

public class Router erweitert Thema {

/** 
* 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 Klasse 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])); 
} 

}

/* * Dateiname: NetworkBoot.java * Public Class Name: Netzwerkbootpaßwortes * */

Import java.io.IOException;

importieren java.net.DatagramPacket;

importieren java.net.DatagramSocket;

importieren Sie java.net.InetAddress;

/** * * NA1 Projekt 2 Frühjahr 2009 Semester * @author Sunny Jain * * */

public class Netzwerkbootpaßwortes {

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(); 
    } 
} 

}