IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Java Discussion :

Compréhension systèmes répartis Java


Sujet :

Langage Java

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2014
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2014
    Messages : 6
    Points : 9
    Points
    9
    Par défaut Compréhension systèmes répartis Java
    Bonjour,

    Dans le cadre d'un cours sur les sytèmes réparties on m'a demandé de faire un code client serveur avec un client qui envoie une classe au serveur avec des variables et nom de la méthode qu'il veut utiliser et le serveur fait le calcul. J'ai réussi à faire fonctionner mon code mais je ne comprends pas vraiment comment il réussit à fonctionner (par magie :/ ). Ce que je ne comprends pas réellement c'est comment le serveur est il capable de comprendre qu'une classe existe alors qu'il ne la lit pas et ne la compile pas lui même.

    Code client
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    package client;
     
    import java.awt.DisplayMode;
    import java.io.BufferedInputStream;
    import java.io.BufferedReader;
    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.ObjectInputStream;
    import java.io.OutputStream;
    import java.net.InetAddress;
    import java.net.Socket;
    import java.util.Scanner;
     
    import commun.ByteStream;
     
    public class MainClient {
     
    	static ByteStream convertisseur = new ByteStream();
    	static Socket ClientSoc;
     
    	// méthode permettant d'envoyer au serveur un message
    	public static int sendToServer(String a, String b, File fichier,
    			String nomClasse, String nomMethode) throws IOException {
     
    		InetAddress ip = InetAddress.getLocalHost();
    		int port = 2555;
     
    		try {
    			// on paramètre la connexion tcp
    			ClientSoc = new Socket(ip, port);
    			InputStream din = ClientSoc.getInputStream();
    			OutputStream dout = ClientSoc.getOutputStream();
    			// convertion des variables et envoie dans le stream
    			convertisseur.toStream(dout, a);
    			convertisseur.toStream(dout, b);
    			convertisseur.toStream(dout, nomClasse);
    			convertisseur.toStream(dout, nomMethode);
    			convertisseur.toStream(dout, fichier);
    			// récupération du résultat
    			return convertisseur.toInt(din);
    			// ClientSoc.close();
    			// ne pas fermer la socket sinon le message de retour ne parviens
    			// pas au client.
     
    		} catch (Exception ex) {
    		}
     
    		// si on a eu une erreur il faut quand même retourné une string donc on
    		// envoie le message error
    		return (-1);
     
    	}
     
    	private static void lectureUtilisateur() throws IOException,
    			ClassNotFoundException {
    		String a, b;
    		Scanner sc = new Scanner(System.in);
    		int retour;
    		String nomClasse, nomMethode;
    		// fichier contenant la classe à envoyer
    		File fichier = new File("Calc.class");
    		System.out.println("chemin du fichier :" + fichier.getAbsolutePath());
     
    		System.out.println("Entrez la valeur de a :");
    		// on lit la valeur de a et on le transforme en string pas de
    		// vérification utilisateur
    		a = sc.nextLine();
    		System.out.println("Entrez la valeur de b :");
    		// on lit la valeur de b et on le transforme en string pas de
    		// vérification utilisateur
    		b = sc.nextLine();
    		System.out.println("la valeur de a est : " + a
    				+ "; la valeur de b est " + b + "");
    		System.out.println("envoie du calcul au serveur");
    		// on lit le fichier comme ça si on décide de changer la classe il
    		// suffira seulement de changer le répertoire d'accès
    		// au fichier que l'on pourrait placer dans les arguments
    		//pas le choix utiliser la chaine de caractère
    		nomClasse = "Calc";
    		// obliger de donner le nom de la méthode car je n'ai pas trouver
    		// d'autres moyens
    		nomMethode = "calc";
    //		System.out.println(nomClasse);
    		retour = sendToServer(a, b, fichier, nomClasse, nomMethode);
    		if(retour== (-1)){
    			System.out.println("Erreur!");			
    		}else{
    			System.out.println("votre réponse est : " + retour + "");
    		}
    	}
     
    	private static void display() throws Exception {
    		String strMsg;
    		String msgFromServer;
     
    		int choice;
     
    		while (true) {
    			System.out.println("\n[ DISPLAY ]");
    			System.out.println("1. faire une addition");
    			System.out.println("2. Exit");
    			System.out.print("\nEnter Choice :");
     
    			BufferedReader br = new BufferedReader(new InputStreamReader(
    					System.in));
    			choice = Integer.parseInt(br.readLine());
    			if (choice == 1) {
    				lectureUtilisateur();
    			} else if (choice == 2) {
    				ClientSoc.close();
    				System.exit(1);
    			} else {
     
    			}
    		}
    	}
     
    	public static void main(String[] args) throws Exception {
    		// TODO Auto-generated method stub
     
    		display();
    	}
    }
    Code coté serveur
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
     
     
    import java.io.BufferedInputStream;
    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.ObjectInputStream;
    import java.io.OutputStream;
    import java.lang.reflect.Method;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.text.DateFormat;
    import java.text.SimpleDateFormat;
    import java.util.Calendar;
    import java.util.Date;
     
    public class MainServer {
     
    	public static void main(String[] args) throws IOException {
    		// TODO Auto-generated method stub
     
    		Socket clientSoc;
    		ServerSocket serverSoc;
    		int portNumber = 2555;
    		serverSoc = new ServerSocket(portNumber);
    		System.out.println("Serveur allumé");
    		while (true) {
    			// on accepte tous les socket entrant
    			clientSoc = serverSoc.accept();
    			TCPServerThread serverThread = new TCPServerThread(clientSoc);
    		}
     
    	}
     
    }
     
    //utilisation d'un threads afin de gérer plusieurs clients
    class TCPServerThread extends Thread {
    	Socket ClientSoc;
    	InputStream din;
    	OutputStream dout;
    	static ByteStream convertisseur= new ByteStream();
     
    	TCPServerThread(Socket soc) {
    		try {
    			ClientSoc = soc;
    			din=ClientSoc.getInputStream();
    			dout=ClientSoc.getOutputStream();
    			System.out.println("TPC Client Connected ...");
    			start();
    		} catch (Exception ex) {
    		}
    	}
     
    	@Override
    	public void run() {
    		String a,b,nomClasse,nomMethode;
    		int retour;
    		//on rajoute la date pour les doublons si plusieurs clients demande le calcul
    //		DateFormat df = new SimpleDateFormat("MM-dd-yyyy HH-mm-ss");
    //		Date today = Calendar.getInstance().getTime();
    		//double \ pour l'escape choisir le répertoire bin du projet java pour mettre le .class
    		String nomFichier = "D:\\Documents\\Workspace_eclipse\\tp1-server\\bin\\Calc.class";
    //		nomFichier.replaceAll("[\\W]|_","");
    		System.out.println(nomFichier);
    		File fichier=new File(nomFichier);
     
     
    		while (true) {
    			try {
     
     
    				// In...
    //				msg = din.readUTF();
    				//réception du stream par le serveur. l'ordre est important pour savoir que a est a et b est b
    				a = convertisseur.toString(din);
    				b = convertisseur.toString(din);
    				nomClasse=convertisseur.toString(din);
    				nomMethode=convertisseur.toString(din);
    //				System.out.println(a+b);
    				convertisseur.toFile(din, fichier);
    				System.out.println("réception du fichier en cours");
    				//on regarde s'il y a une classe dans le stream
    				FileInputStream lecture = new FileInputStream(fichier);
    //				InputStream interm = lecture;
    //				System.out.println("succes 11");
    //				ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(lecture));
    //				System.out.println("succes 2");
    //				Object objet = ois.readObject();
    //				System.out.println("succes 3");
    //				Class classe = objet.getClass();
    				Class classe = Class.forName(nomClasse);
    				Object cls = classe.newInstance();
    				Class[] types = { String.class, String.class };
    				Method m = classe.getMethod("add", types);
    				Object retourPartiel =  m.invoke(cls, a,b);
    //				System.out.println(retourPartiel);
    				retour = (int) retourPartiel;
    				convertisseur.toStream(dout,retour);
    			} catch (Exception ex) {
    			}
    		}
    	}
    }

  2. #2
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Citation Envoyé par blafarus Voir le message
    Ce que je ne comprends pas réellement c'est comment le serveur est il capable de comprendre qu'une classe existe alors qu'il ne la lit pas et ne la compile pas lui même.
    Il ne la lit pas => est-ce que tu lit explicitement la moindre de tes autres classes présentes dans ton code? Non, tu laisse java lire tout ce qui est dans son classpath.
    Il ne la compile pas => C'est ton appel à javac qui a compilé le fichier et rien d'autres. C'est comme pour ton Server.class et ton Client.class

    Par contre si tu imagine à un seul moment que ton code a transféré la classe a exécuté du client vers le serveur, tu te fourre le doigt dans l'oeil. Ton code marche parce que la classe Calc est déjà présente dans le serveur.

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2014
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2014
    Messages : 6
    Points : 9
    Points
    9
    Par défaut
    j'avais un petit doute suite à tes propos quand à l'envoie de la classe donc j'ai mis en commentaire l'envoie du byte code au serveur et celui ci ne réponds plus. Comme quoi il est obligé de l'avoir avant de pouvoir travailler dessus.

    Ce qui vient confirmer que pour chaque projet il y a un espace mémoire différent et une JVM différente.

    Donc si un projet veux travailler sur une classe qu'il ne connait pas il a besoin de trouver le bytecode de cette classe dans sa mémoire, est ce bien ça?

  4. #4
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Bon on n'a pas la classe convertisseur.

    Il faut que tu comprenne comment fonctionne le chargement des classes en java.

    Ca passe par le classloader et le classloader il a en gros une liste de trucs à regarder quand on lui demande une classe. Ici tu lui demande la classe "Calc".

    Dans ton cas, si le transfert marche, c'est suite à une série de coup de chances:

    Ton application n'est pas packagée dans un jar => le classloader travaille avec un répertoire que ton ide (ou ta ligne de commande) lui a filé. Premier coup de bol, ca ne marchera pas avec un jar
    Il s'agit dans ton cas de D:\\Documents\\Workspace_eclipse\\tp1-server\\bin\\
    Par hardcodage, tu as été stocker la classe qui t'es fournie dans ce dossier sous le nom de Calc.class. Deuxième coup de bol, c'est justement le nom de la classe. Ca ne marchera pas avec une autre classe.
    Troisième coup de bol, nulle part avant, tu n'a essayé de charger cette class. En effet le classloader essaie une et une seule fois de charger la classe en question, si il ne la trouve pas il la marque définitivement dans sa liste comme inexistante.
    Quatrième coup de bol, ta classe ne dépend d'aucune autre classe, et ne dispose pas d'inner class.
    Cinquième coup de bol, tu as un seul client avec ce nom de classe.


    Bref tu marche sur un fil très très mince.

    Ce que tu essaie, en gros, de faire, c'est faire réaliser une opération par le serveur, opération qui est définie dans une sorte de "plugin" que le client fourni au serveur. Et faudrait que ça marche dans tous les cas.

    Pour ça, il faut travailler un peu plus proprement.
    Tout d'abord l'ensemble des classes nécessaires au calcul doivent être empaquetée, par exemple, dans un jar.
    Ensuite le client transmettra le jar (et non pas juste un .class) au serveur + les autres infos que tu as déjà genre méthode, classe, etc.
    Le serveur va stocker le jar dans un dossier temporaire, sous un nom temporaire, peu importe.
    Il va créer un nouveau classloader à partir de ce jar (ce qui permettra d'avoir un classloader par requete et donc une isolation entre clients). Je te recommande le URLClassLoader qui est adapté à ce genre de besoin.
    Il va demander à ce classloader de charger ladite classe, trouver la dite méthode et l'exécuter. Bref comme tu fais comme avant sauf qu'en lieu et place de Class.forName(nomClasse) tu fera classloader.loadClass(nomClasse)

  5. #5
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2014
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2014
    Messages : 6
    Points : 9
    Points
    9
    Par défaut
    OK merci de tes conseils. Je me doutais que le cas ne serait pas faisable avec plusieurs clients car j'avais déjà essayé. Certes la manière n'est pas bonne du tout (au début je comptais partir sur du RMI) mais en faisant au plus simple on y arrive quand même. En tout cas merci de ta réponse.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Système expert Java
    Par Fukoro dans le forum Général Java
    Réponses: 0
    Dernier message: 26/04/2012, 12h37
  2. Renseignements sur les systèmes répartis
    Par xeon59 dans le forum Autres systèmes
    Réponses: 1
    Dernier message: 24/11/2009, 17h23
  3. HPC Server et systèmes répartis
    Par hafed dans le forum Windows
    Réponses: 1
    Dernier message: 16/05/2009, 17h25
  4. Date et heure système avec java.sql
    Par reverse_engineer dans le forum Langage
    Réponses: 3
    Dernier message: 17/07/2008, 10h00
  5. Récupérer des propriétés système en Java
    Par nikalkal dans le forum Général Java
    Réponses: 9
    Dernier message: 05/05/2006, 16h50

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo