Créer un reseau en java

Bonjour,
Je voulais faire un programme en socket java, qui permet de créer un réseau virtuel de telle façon a ce que une machine qui exécute le programme envoie un fichier, qui passe par des machine intermédiaire exécutant eux aussi le programme avant d'arriver a la destination finale.
Le problème c'est que envoyer un fichier d'une machine a une autre s marche en spécifiant les adresse IP du client et serveur, mais entre plusieurs machine qui joueront le rôle de machine intermédiaire (routeur) pour acheminer le fichier ca j'ai aucune idée.
Je vous en pris si vous avez une idée, des pistes, bout de programme pour s'y faire aidez moi.
Et merci d'avance.

26 réponses

Résumé de la discussion

Plusieurs intervenants discutent de la création d'un réseau virtuel en Java utilisant des machines intermédiaires qui relaient un fichier entre une source et une destination, par sockets et IP. Des machines intermédiaires seraient des serveurs: le fichier est adressé au serveur, qui peut exécuter le programme et relayer ensuite vers le client final ou vers un autre serveur intermédiaire. Des propositions évoquent soit une liste d'adresses des nœuds à traverser, soit un en-tête indiquant le prochain relais ou un routage dynamique basé sur des métriques statiques entre machines. Pour une approche pratique, des exemples montrent qu'un chemin simple impliquant une chaîne de serveurs locaux peut constituer une première étape, même sans routeur dédié, avant d'aborder des scénarios plus complexes.

Bobot (l’IA à votre service)
  1. Modérateur
    J'avoue que ça fais plusieurs fois que je vois tes messages et que je n'y réponds pas, mais c'est parce que ton problème est assez compliqué et que je n'ai pas trop le temps en ce moment pour m'y consacrer d'avantage. ça ira mieux dans une semaine ;-)
    Donc si tu as le temps d'attendre jusque là je regarderai tout ça attentivement et te dirai ce que j'en pense. Mais pour l'instant je n'ai guère plus de temps à consacrer au forum que quelques petites aides hyper-faciles qui me prennent 5 minutes maxi, ce qui n'est pas ton cas. J'espère que tu comprendras :)
    1. bonjour
      je vous est mis le sujet afin que vous puissiez comprendre le sujet il s'agit d'une application qui fait le transfert d'un fichier en utilisant un socket java a travers un réseau de recouvrement
      s'il vous plait si vous avez une idée comment s'y faire n'hésiter pas

      merci de votre aide d'avance
      Mise en place du réseau de recouvrement
      Les équipements cibles doivent disposer d'une application permettant la réception des contenus. Ces applications
      sont interconnectées au moyen d'éléments d'interconnexion (dénommés ci-après routeurs de recouvrement). Par
      le maillage de leur interconnexion, les routeurs de recouvrements assurent le routage et le transfert des contenus
      vers les équipements cibles. Ces fonctionnalités supposent que les routeurs de recouvrement disposent d'une
      application dédiée.
      Cette première étape consiste à mettre en place l'interconnexion logique entre les équipements cibles. Dans cette
      version, on se limitera à une interconnexion statique prévue à l'avance.
      A chaque application sera associée une adresse logique sur le réseau de recouvrement. Le choix des critères
      d'attribution de ces adresses est laissé à votre convenance.
      1. j'ai reussi en se basant juste sur les numero de port
        et voila le code j'ai savoir q est ce que t on pense
        j ai simuler un envoi de client vers serveur en passant par A et B et C
        s il te plait dit q est ce que tu en pense
        et merci de votre aide
        pour la classe commun j ai gardé la même:
        /*
        * To change this template, choose Tools | Templates
        * and open the template in the editor.
        */

        client
        public class cl
        {
        public static void main(String[] args) throws IOException
        {
        Socket sock = new Socket(InetAddress.getLocalHost(),9001);

        commun.transfert(new FileInputStream("C:\\M1\\oth.png"),sock.getOutputStream(),true);

        sock.close();
        }
        }

        A

        public class A
        {
        public static void main(String[] args) throws IOException
        {
        Socket sock = new ServerSocket(9001).accept();

        //recevoir
        commun.transfert(
        sock.getInputStream(),
        new FileOutputStream("C:\\M2\\f1.png"),
        true);

        //envoyer//
        Socket sock2 = new Socket(InetAddress.getLocalHost(),9002);
        commun.transfert(new FileInputStream("C:\\M2\\f1.png"),sock2.getOutputStream(),true);

        //envoyer//

        sock.close();
        }
        }

        B

        public class B
        {
        public static void main(String[] args) throws IOException
        {
        Socket sock2 = new ServerSocket(9002).accept();

        //recevoir
        commun.transfert(
        sock2.getInputStream(),
        new FileOutputStream("C:\\M3\\finale.png"),
        true);

        int a=0;
        int port;
        //envoyer a 9004//
        if(a==1)
        {
        port=9004;
        }
        else
        port=9003;

        Socket sock3 = new Socket(InetAddress.getLocalHost(),port);
        commun.transfert(new FileInputStream("C:\\M3\\finale.png"),sock3.getOutputStream(),true);

        sock2.close();
        }
        }

        C

        public class C
        {
        public static void main(String[] args) throws IOException
        {
        Socket sock3 = new ServerSocket(9003).accept();

        //recevoir
        commun.transfert(
        sock3.getInputStream(),
        new FileOutputStream("C:\\M4\\finale.png"),
        true);

        //envoyer//
        Socket sock4 = new Socket(InetAddress.getLocalHost(),9004);
        commun.transfert(new FileInputStream("C:\\M4\\finale.png"),sock4.getOutputStream(),true);

        sock3.close();
        }
        }

        public class srv
        {
        public static void main(String[] args) throws IOException
        {
        Socket sock4 = new ServerSocket(9004).accept();

        commun.transfert(
        sock4.getInputStream(),
        new FileOutputStream("C:\\M5\\finale.png"),
        true);

        sock4.close();
        }
        }
        1. je pense que on aura pas besoin des machine virtuel car la connexion est logique donc on vas pas se soucier des carte réseau et port et tous ca..
          qu'est ce que t en pense ??
          1. parce que la j'ai installé vmware avec 2 macine et je compte faire l 3 machine
            1. ok j'ai compris
              confirme moi ca s'il te plait:
              s'il s'agit de plusieur serveur il suffit de refaire ce code sur chaque main du fichier serveur
              Commun.repeter("A",null,new File("D:\\test2.png"));

              donc (classeB=client) classeA=seveur
              et la classe comun c est c'est ca:

              public class Commun
              {
              public static final int port = 9001;

              public static void transfert(String role, InputStream in, OutputStream out, boolean closeOnExit) throws IOException
              {
              System.err.println(role+" transfert");

              byte buf[] = new byte[1024];

              int n;
              while((n=in.read(buf))!=-1)
              out.write(buf,0,n);

              if (closeOnExit)
              {
              in.close();
              out.close();
              }
              }

              public static void envoi(String role, LinkedList<String> serveurs, File fichier) throws IOException
              {
              System.err.println(role+" envoi");
              // Ouverture de la communication
              Socket sock = new Socket(serveurs.getFirst(),Commun.port);
              ObjectOutputStream out = new ObjectOutputStream(sock.getOutputStream());

              // Envoi de l'en-tête
              out.writeInt(serveurs.size());
              for (String srv : serveurs)
              out.writeUTF(srv);

              // Envoi du fichier
              Commun.transfert(
              role,
              new FileInputStream(fichier),
              out,
              true);

              // Fermeture de la communication
              sock.close();
              }

              public static LinkedList<String> recevoir(String role, File fichier) throws IOException
              {
              System.err.println(role+" recevoir");

              // Ouverture d'une communication
              Socket sock = new ServerSocket(Commun.port).accept();
              ObjectInputStream in = new ObjectInputStream(sock.getInputStream());

              // Réception de l'en-tête
              int n = in.readInt();

              LinkedList<String> serveurs = new LinkedList<String>();

              for (int i=0; i<n; i++)
              serveurs.add(in.readUTF());

              // Réception du fichier
              Commun.transfert(
              role,
              in,
              new FileOutputStream(fichier),
              true);

              // Fermeture de la communication
              sock.close();

              return serveurs;
              }

              public static void repeter(String role, LinkedList<String> serveurs, File fichier) throws IOException
              {
              // Client
              if (serveurs!=null && serveurs.size()>0)
              envoi(role, serveurs,fichier);

              // Serveur
              serveurs = recevoir(role, fichier);
              serveurs.removeFirst();

              // On recommence
              repeter(role, serveurs, fichier);
              }

              }

              donc si je teste sur une machine virtuel:
              client=classeB
              et sur chaque serveur je met le code de la classe A
              reste juste a changer la liste au fonction de nombre et les adresse des serveur intermedaire.
              j attend ta confirmation sur ca s'il te plait
              et merci de votre comprhension.
              1. Modérateur
                C'est un peu plus compliqué que ça, car le "serveur" devient à son tour "client" lorsqu'il a reçu des données. Donc on ne peut pas dire client=classeB ou serveur=classeA, c'est pour ça que j'avais préféré tout faire dans la classe Commun car en fait ils ont tous le même comportement.
                La seule différence entre A et B, c'est qu'au lancement A envoie un fichier. Mais on peut très bien imaginer qu'on démarre tout le monde avec une classe B (ils attendent tous des fichiers) et de temps en temps on envoie un fichier (avec la classe A ou une autre).
              2. oui je pense que j'ai compris la problématique
                dnc pour pouvoir tester le transfert entre plusieur machine tu propose quoi comme code sur le client et le serveur si on va pas reprendre le code de la classe A et B
                merci de votre comprehension
              3. Modérateur
                Tu dois lancer le programme role=B sur toutes tes machines. Et une fois que c'est fait envoyer un fichier avec le programme role=A, éventuellement modifié pour s'arrêter une fois le fichier envoyé, et attendre de voir ce que font les machines B avec. À la fin il est possible que tu ais une machine role=C, qui reçoive le fichier, mais là encore ce n'est qu'un cas particulier de B, où la liste arrive vide.
              4. je pense que c'est pas claire s'il te plait pourrai tu me donner le code par ce que la ca commence a me prendre la tete
                code client =?
                code serveur=?
                code commun =?
                s'il te plait.
                et merci de votre comprehension.
            2. si j'ai bien compris
              s'il s'agit de plusieur serveur il suffit de refaire ce code sur chaque main du fichier serveur
              Commun.repeter("A",null,new File("D:\\test2.png"));
              donc (classeB=client) classeA=seveur

              reste une chose et vu que le seveur doit transmeetre la liste tu pense pas que ce null( prametre2 de la methode repeter) est anormal
              merci de votre comprension
              1. Modérateur
                C'est moi qui ait décidé dans la méthode repeter que le paramètre "serveurs" pouvait prendre la valeur null. Si on est client, on a une liste à envoyer, donc une liste avec plusieurs serveurs cibles (l'un après l'autre) mais lorsqu'on est serveur, on attend une liste, mais donc au départ on ne connait pas sa valeur, c'est pour ça qu'on met null.

                null -> serveur attend une llste
                non-null -> client envoie la liste
            3. pour la classe commun j'ai gardé les methode repeter et envoi et recevoir transert
              et pour la classe client voila le code:(j pense que le serveur quand il recoit la liste il la relay pas)
              public class client
              {
              public static void main(String[] args) throws IOException
              {

              // Ouverture de la communication

              new Thread()
              {
              @Override
              public void run()
              {
              final LinkedList<String> serveurs = new LinkedList<String>();
              serveurs.add("localhost");
              serveurs.add("localhost");
              serveurs.add("localhost");
              try {
              Commun.repeter("Thread 2",serveurs,new File("C:\\M1\\oth.png"));
              } catch (Exception e) {
              e.printStackTrace();
              }
              }
              }.start();
              }

              // Fermeture de la communication

              }

              et pour la classe serveur
              public class serveur
              {

              public static void main(String[] args) throws IOException
              {
              // Serveur
              new Thread()
              {
              @Override
              public void run()
              {
              try {
              Commun.repeter("Thread 1",null,new File("D:\\t15.png"));
              } catch (Exception e) {
              e.printStackTrace();
              }
              }
              }.start();
              1. Modérateur
                Comme je l'avait dit au moment où j'ai publié le code, il y a encore des bugs quand on est en local, parce qu'il faudrait temporiser entre le moment où on ferme la socket et le moment où on la réouvre.
                Mais si tu testes ça sur plusieurs machines ça devrait aller.

                Remarque : si tu as deux main différents, les threads ne servent plus à rien (voir les classes A et B)
            4. s'il te plait j'ai du mal pour tester le code
              pourrai je avoir une reponse meme si pour un dernier fois
              merci de votre comprehension
              1. Modérateur
                1) Tu copies-colles la classe Commun dans un fichier Commun.java, tu compiles et tu exécutes.

                2) Tu copies-colles les classes A et B dans deux fichiers A.java et B.java, et tu exécutes A, puis B

                Tu choisis l'une des deux méthodes au choix, ça fera la même chose (j'avais fait la deuxième uniquement parce que tu ne comprenais pas la première)
                Je ne vois vraiment pas ce qu'il y a de compliqué à tester ça...
            5. bonjour,
              j'attende toujours ta reponse
              et merci de votre compréhension
              1. bon je galére un peu avec ce code pour le faire marcher stp si t une idé sur les bloc q il faut corriger n'hesiter a me le faire passer ca ma bcp m'aider pour econimser le temps car je pense que j'essayé le max mais j arrive pas
                sachant que j'ai commencé a reflichir sur la partie routage et j'ai imaginé un petit peu le scenario
                1. Modérateur
                  Les threads permettent de lancer deux executions en parallèles, ce qui me permet de lancer le serveur dans le Thread1, et le client dans le Thread2.

                  Le paramètre role ne sert à rien, c'est juste pour débugger. En effet comme les deux threads tournent en même temps sur la même console, on ne sait plus trop qui affiche quoi. Avec le role on peut savoir qui affiche quoi. Par exemple au début, les deux threads sont lancés : Thread1 (serveur) affiche "Thread 1 recevoir", et Thread2 (client) affiche "Thread 2 envoi".

                  Mais tu peux très bien rajouter deux classes supplémentaires, avec deux main, le premier avec le code de Thread1, l'autre avec le code de Thread2.

                  class A
                  {
                  	public static void main(String...args) throws Exception
                  	{
                  		Commun.repeter("A",null,new File("D:\\test2.png"));
                  	}
                  }
                  
                  class B
                  {
                  	public static void main(String...args) throws Exception
                  	{
                  		LinkedList<String> serveurs = new LinkedList<String>();
                  			serveurs.add("localhost");
                  			serveurs.add("localhost");
                  			serveurs.add("localhost");
                  			
                  		Commun.repeter("B",serveurs,new File("D:\\test1.png"));
                  	}
                  }

                  Ce sera peut-être plus simple comme ça ;-)
                  1. je te demande juste une petite explication a partir du bloc de la methode main jusqu'a la fin c'est la ou j'ai du mal un peu
                    merci de votre comprehension
                    1. j'avoue que j'ai un peux du mal a bien assmiler toute les parties du code
                      l'utilisation des thread c m a un peut gener
                      le faite de ne pas supposer un liste des serveur au prelable
                      1. ca ma pris un peut de temps de comprendre ton code mais je comprend pas a quoi sert le parametre role
                        merci pour ta reponse
                        1. bonjour,
                          je commence a penser a installer des machiness virtuel pour pouvoir tester, en attendant j'ai essayé de faire le code qui permet de relayer le fichier au niveau de chaque serveur, du coup au niveau du serveur1 aprés avoir recu le fichier et le tableau du chemin il doit crer une nouvelle socket d'envoi du faite q il va se transformer au client j'ai propsé le code qui doit se repter sur chaque serveur intermediare
                          le probleme c'est java il accepte pas de crer une nouvelle soket d'envoi sachant q'une socket de reception autant que serveur est deja cré. voila le code que j'ai essayé si t une idé comment s'y faire n'hesiter pas a me debloquer
                          le code c'est une suite de ce que t coder au niveau serveur
                          donc j'ai gardé le meme principe en creant une nouvelle socket avec une nouvelle adresse t[0] je pense que c'est le code qui je doit mettre sur chaque serveur intermedaire .

                          et merci de votre comprension

                          // Affichage de l'en-tête
                          //bloc qui se repete sur chaque serveur intermediare
                          for (String s : tab)
                          System.out.println(s);

                          if(tab[0]!="client" ||tab[0]!=null) //si la case contient null il passe a la suivante
                          //creation nouveau socket d'envoi
                          Socket sock2 = new Socket(tab[0],9001);

                          tab[0]=null; //facon pour supprimer le premier saut du chemin qui servira rien

                          ObjectOutputStream out = new ObjectOutputStream(sock.getOutputStream());

                          //envoi du tableau
                          out.writeInt(tab.length);
                          for (int i=0; i<tab.length; i++)
                          out.writeUTF(tab[i]);

                          // Envoi du fichier
                          commun.transfert(new FileInputStream(new File("C:\\M2\\logo.png")),out,true);
                          1. Modérateur
                            Tu ne peux pas ouvrir sock et sock2 en même temps sur le même port.
                            Il faut attendre que sock soit fermée (après le transfert) pour ouvrir sock2.
                            D'ailleurs ici ton sock2 ne sers à rien, tu peux le supprimer.

                            Moi j'avais mis le code client et serveur dans deux main, mais il faudrait plutôt en faire des méthodes static, vu que chaque serveur va devoir lancer les deux l'un après l'autre.

                            Pour t'éviter ta manipulation de "null" dans ton tableau tu peux utiliser une LinkedList et faire des removeFirst.

                            Voici un code, qui peut t'aider à bien continuer, je ne dis pas qu'il fonctionne correctement, d'ailleurs j'ai moi aussi des problèmes avec le bind mais si au lieu de faire des throws tu gère les Exception avec des try/catch ça devrait mieux passer (idée : si tu lèves BindException, tu fermes la socket, tu attends 1 seconde, et tu réessayes)

                            import java.io.File;
                            import java.io.FileInputStream;
                            import java.io.FileOutputStream;
                            import java.io.IOException;
                            import java.io.InputStream;
                            import java.io.ObjectInputStream;
                            import java.io.ObjectOutputStream;
                            import java.io.OutputStream;
                            
                            import java.net.ServerSocket;
                            import java.net.Socket;
                            
                            import java.util.LinkedList;
                            
                            public class Commun
                            {
                            	public static final int port = 9001;
                            	
                            	public static void transfert(String role, InputStream in, OutputStream out, boolean closeOnExit) throws IOException
                            	{
                            		System.err.println(role+" transfert");
                            		
                            		byte buf[] = new byte[1024];
                            		
                            		int n;
                            		while((n=in.read(buf))!=-1)
                            			out.write(buf,0,n);
                            		
                            		if (closeOnExit)
                            		{
                            			in.close();
                            			out.close();
                            		}
                            	}
                            	
                            	public static void envoi(String role, LinkedList<String> serveurs, File fichier) throws IOException
                            	{
                            		System.err.println(role+" envoi");
                            		// Ouverture de la communication
                            		Socket sock = new Socket(serveurs.getFirst(),Commun.port);
                            		ObjectOutputStream out = new ObjectOutputStream(sock.getOutputStream());
                            	
                            		// Envoi de l'en-tête
                            		out.writeInt(serveurs.size());
                            		for (String srv : serveurs)
                            			out.writeUTF(srv);
                            						
                            		// Envoi du fichier
                            		Commun.transfert(
                            			role,
                            			new FileInputStream(fichier),
                            			out,
                            			true);
                            		
                            		// Fermeture de la communication
                            		sock.close();
                            	}
                            	
                            	public static LinkedList<String> recevoir(String role, File fichier) throws IOException 
                            	{
                            		System.err.println(role+" recevoir");
                            					
                            		// Ouverture d'une communication
                            		Socket sock = new ServerSocket(Commun.port).accept();
                            		ObjectInputStream in = new ObjectInputStream(sock.getInputStream());
                            		
                            		// Réception de l'en-tête
                            		int n = in.readInt();
                            		
                            		LinkedList<String> serveurs = new LinkedList<String>();
                            		
                            		for (int i=0; i<n; i++)
                            			serveurs.add(in.readUTF());
                            							
                            		// Réception du fichier
                            		Commun.transfert(
                            				role,
                            				in,
                            				new FileOutputStream(fichier),
                            				true);
                            		
                            		// Fermeture de la communication
                            		sock.close();
                            				
                            		return serveurs;
                            	} 
                            	
                            	public static void repeter(String role, LinkedList<String> serveurs, File fichier) throws IOException
                            	{		
                            		// Client
                            		if (serveurs!=null && serveurs.size()>0)
                            			envoi(role, serveurs,fichier);
                            		
                            		// Serveur
                            		serveurs = recevoir(role, fichier);
                            		serveurs.removeFirst();
                            		
                            		// On recommence
                            		repeter(role, serveurs, fichier);
                            	}
                            	
                            	public static void main(String...args) throws IOException
                            	{
                            		// Serveur
                            		new Thread() 
                            		{
                            			@Override
                            			public void run()
                            			{
                            				try {
                            					repeter("Thread 1",null,new File("D:\\test2.png"));
                            				} catch (Exception e) {
                            					e.printStackTrace();
                            				}
                            			}
                            		}.start();
                            				
                            		final LinkedList<String> serveurs = new LinkedList<String>();
                            			serveurs.add("localhost");
                            			serveurs.add("localhost");
                            			serveurs.add("localhost");
                            		
                            		// Client
                            		new Thread() 
                            		{
                            			@Override
                            			public void run()
                            			{
                            				try {
                            					repeter("Thread 2",serveurs,new File("D:\\test1.png"));
                            				} catch (Exception e) {
                            					e.printStackTrace();
                            				}
                            			}
                            		}.start();
                            	}
                            }
                        2. merci de votre réponse
                          l'idée de changer le port ca peut marcher mais moi je cherche a remplir des table de routage pour spécifier des chemins, donc j'ai besoin d'adresse ip pour identifier les machine
                          1. Modérateur
                            Vu que tu n'as qu'une seule machine, tes tables de routage seront très limitées !
                            Mais dans l'absolu ton code doit pouvoir marcher si la liste des adresses ip sont ["localhost", "localhost", "localhost"] sans même avoir changer de port.
                            Lorsque le serveur reçoit le fichier (de lui même) il interrompt la communication, il peut donc réutiliser le même port pour relayer le fichier (à lui même du coup)
                          2. Contributeur
                            Pas faux aussi :-)
                        3. Contributeur
                          Pas forcément obligé de simuler plusieurs machines, il suffit de changer le port d'écoute.

                          Soit on a des conditions réelles, soit il faut tout faire pour s'en approcher au MAX.

                          Ou alors virtualiser des machines linux sur ton PC, mais bon ça nécessite un peu de puissance.
                          • 1
                          • 2