2009-05-09 5 views
1

Je fais mon devoir dans l'architecture de réseau 1, où je dois implémenter un routage de vecteur de distance à chaque noeud.Filetage pour le vecteur de distance qui ne laisse pas tomber les paquets

A chaque nœud, j'ai un thread qui écoute les DatagramPacket entrants contenant des informations de routage provenant de nœuds voisins uniquement sur un port spécifique. Quand un datagramme arrive, le thread traite ce datagramme, et s'il y a des mises à jour dans ses tables de routage internes, alors il envoie ses informations de routage à tous ses voisins. J'essaie de le faire en Java. J'essaye de le faire en Java.

Le problème auquel je suis confronté est que lorsqu'un datagramme arrive, j'ai besoin de le traiter. Si pendant ce temps un autre datagramme arrive, il est supprimé, car le thread traite actuellement les informations. Cela signifie que j'ai une perte d'information.

Quelqu'un peut-il m'aider avec ceci? J'utilise la manière habituelle de lire à partir d'un socket en 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(); 
    } 
} 

Répondre

0

DatagramSocket socket = new DatagramSocket (4445, InetAddress.getByName ("127.0.0.1")); while (true) { try { // note finale octet final [] buf = new 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

Performance note: Il n'est certainement pas efficace d'instancier un nouveau thread pour chaque paquet. Si l'ordre de traitement est important, utilisez un BlockingQueue et disposez d'un tampon de lecture de thread de traitement pré-instancié de manière FIFO. Si l'ordre n'est pas pertinent, utilisez un Executor. (Et si vous voulez vraiment presser les cycles, pensez à recycler ces tampons byte [].) – alphazero

2

Vous pouvez traiter le datagramme reçu dans un thread, afin que votre thread avec l'écouteur socket puisse continuer à recevoir de nouveaux datagrammes.

0

Je ne l'ai pas fait en Java, mais vous pouvez (ou devez) passer plus d'un tampon de datagramme simultané au socket (soit avec plusieurs threads invoquant chacun la méthode de réception synchrone, soit de préférence avec un thread invoquant un méthode de réception asynchrone plus d'une fois). L'avantage de passer plusieurs tampons de datagramme simultanés à la socket est évident: le socket aura toujours un tampon (dans lequel recevoir le prochain datagramme) même s'il a déjà rempli un tampon (avec un datagramme précédent) et passé ce tampon à vous.

Vous pourriez demander, "dans quelle séquence les tampons me seront-ils transmis?" et la réponse à cela est "ça ne devrait pas avoir d'importance". Si la séquence dans laquelle vous traitez les datagrammes est importante, les datagrammes eux-mêmes doivent contenir un numéro de séquence (car les datagrammes peuvent être désordonnés lorsqu'ils sont routés sur le réseau, que vous ayez ou non passé plusieurs simultanément sur le socket local avec une possibilité conséquente de "simultanée" vous est alors restituée hors séquence).

0

Il convient de rappeler UDP est le transport lossy, tout en minimisant la perte de paquets est une bonne idée que vous ne devriez jamais supposer que vous obtiendrez chaque paquet (ou que les paquets arriverez dans l'ordre envoyé les)

1

Ceci est le projet final que j'ai soumis. Il peut s'agir d'une documentation incorrecte et d'une mauvaise utilisation de Java. Comme ce projet s'exécute sur un système local, au lieu d'utiliser une adresse IP différente et le même numéro de port, je le fais d'une autre manière. NetworkBoot.java fournit les détails du voisin initial à chaque routeur.

Merci -Sunny Jain

enter code here 

/* * Nom du fichier: Router.java * Classe publique Nom: Router * */

// --- ~ importations JDK -------------------------------------------------- ----------

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;

/** * * Projet NA1 2 printemps semestre 2009 * @author Jain ensoleillé * * */

routeur public class 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. 
*/ 

classe privée 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])); 
} 

}

/* * Nom du fichier: NetworkBoot.java * Nom public Classe: NetworkBoot * */

importation java.io.IOException;

import java.net.DatagramPacket;

import java.net.DatagramSocket;

import java.net.InetAddress;

/** * * Projet NA1 2 printemps semestre 2009 * @author Jain ensoleillé * * */

NetworkBoot public class {

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

}

Questions connexes