i hope you guys are doing fine (i'm french btw, excuse my english). I have a problem with my project. This involves developing a client-server program. The client part will read from a data file a set of commands that the client will have to make the server execute. I created the ApplicationClient, ApplicationServer, and Commande class but my ApplicationClient isnt running and throws multiples errors while my ApplicationServer has an infinite running loop (running but without end)
I tried to run my ApplicationClient with those 4 arguments for the socket (hostname, port, the command file and the outputfile)
Here is my code :
Application Client class
public class ApplicationClient {
private BufferedReader commandesReader;
private FileWriter printWriter;
private PrintWriter sortieWriter;
private InetAddress hostname;
private int port, s_port;
private ObjectInputStream ois = null;
private ObjectOutputStream oos = null;
private String s_host;
private InetAddress serverHostname;
private int portNumber;
/**
* prend le fichier contenant la liste des commandes, et le charge dans une
* variable du type Commande qui est retournée
*
*/
public Commande saisisCommande(BufferedReader fichier) {
try {
String strCurrentLine = "";
if ((strCurrentLine = fichier.readLine()) != null) {
System.out.println(strCurrentLine);
return new Commande(strCurrentLine);
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
return null;
}
/**
* initialise : ouvre les différents fichiers de lecture et écriture
*/
public void initialise(String fichCommandes, String fichSortie) throws Exception {
//ouverture fichier de lecture
FileReader fichLecture = new FileReader(fichCommandes);
commandesReader = new BufferedReader(fichLecture);
//ouverture fichier de sortie
FileWriter fichEcriture = new FileWriter(fichSortie);
BufferedWriter buff_writer = new BufferedWriter(fichEcriture);
sortieWriter = new PrintWriter(buff_writer);
}
/**
* prend une Commande dûment formatée, et la fait exécuter par le serveur. Le résultat de
* l’exécution est retournée. Si la commande ne retourne pas de résultat, on retourne null.
* Chaque appel doit ouvrir une connexion, exécuter, et fermer la connexion. Si vous le
* souhaitez, vous pourriez écrire six fonctions spécialisées, une par type de commande
* décrit plus haut, qui seront appelées par traiteCommande(Commande uneCommande)
*/
public Object traiteCommande(Commande uneCommande) throws IOException, ClassNotFoundException {
//Création du socket pour permettre la connexion au serveur
Socket clientSocket = new Socket(serverHostname, portNumber);
//Création des flux d'entrée et de sortie en direction du serveur
//Entrée
ois = new ObjectInputStream(clientSocket.getInputStream());
//Sortie
oos = new ObjectOutputStream(clientSocket.getOutputStream());
//Envoi de l'objet uneCommande au serveur
oos.writeObject(uneCommande);
//Résultat renvoyé par le serveur
Object resultat = ois.readObject();
//Fermeture du serveur, exception en cas de problème
Runtime.getRuntime().addShutdownHook(new Thread(){public void run(){
try {
clientSocket.close();
System.out.println("Le serveur est fermé");
} catch (IOException e) { //Gestion des exceptions
}
}});
return resultat;
}
/**
* cette méthode vous sera fournie plus tard. Elle indiquera la séquence d’étapes à exécuter
* pour le test. Elle fera des appels successifs à saisisCommande(BufferedReader fichier) et
* traiteCommande(Commande uneCommande).
*/
public void scenario() throws IOException, ClassNotFoundException {
sortieWriter.println("Debut des traitements:");
Commande prochaine = saisisCommande(commandesReader);
while (prochaine != null) {
sortieWriter.println("\tTraitement de la commande " + prochaine + " ...");
Object resultat = traiteCommande(prochaine);
sortieWriter.println("\t\tResultat: " + resultat);
prochaine = saisisCommande(commandesReader);
}
sortieWriter.println("Fin des traitements");
}
/**
* programme principal. Prend 4 arguments: 1) “hostname” du serveur, 2) numéro de port,
* 3) nom fichier commandes, et 4) nom fichier sortie. Cette méthode doit créer une
* instance de la classe ApplicationClient, l’initialiser, puis exécuter le scénario
*/
public static void main(String[] args) throws Exception {
if(args.length != 4) {
System.out.println("Vous devez spécifier 4 arguments !");
} else {
ApplicationClient applicationClient = new ApplicationClient();
applicationClient.serverHostname = InetAddress.getByName(args[0]);
applicationClient.portNumber = new Integer(args[1]);
applicationClient.initialise(args[2], args[3]);
applicationClient.scenario();
applicationClient.sortieWriter.close();
}
}
}
ApplicationServer
public class ApplicationServeur {
private ServerSocket sockServer;
private ObjectInputStream ois = null;
private ObjectOutputStream oos = null;
private String m_rep_source;
private String m_rep_classes;
Class chargement_classe = null;
HashMap<String, Object> liste_objets = new HashMap<String, Object>();
ArrayList<Class<?>> liste_classes = new ArrayList<Class<?>>();
/**
* prend le numéro de port, crée un SocketServer sur le port
*/
public ApplicationServeur (int port, String rep_source, String rep_classes) throws IOException {
//Définition du répertoire source et du répertoire où les classes sont présentes
m_rep_source = rep_source;
m_rep_classes = rep_classes;
//Socket
sockServer = new ServerSocket(port);
}
/**
* Se met en attente de connexions des clients. Suite aux connexions, elle lit
* ce qui est envoyé à travers la Socket, recrée l’objet Commande envoyé par
* le client, et appellera traiterCommande(Commande uneCommande)
*/
public void aVosOrdres() throws IOException {
while(true) {
Object messageRetour = null;
//Ouvrir le socket ainsi que les flux d'entrée et de sortie
Socket socketConnexion = sockServer.accept();
//Entrée
ois = new ObjectInputStream(socketConnexion.getInputStream());
//Sortie
oos = new ObjectOutputStream(socketConnexion.getOutputStream());
try {
//Leture de l'envoi à travers le socket
Commande command = (Commande) ois.readObject();
traiteCommande(command);
//Informer le client en renvoyant une requête qui servira de réponse
oos.writeObject(messageRetour);
if(messageRetour == null) {
System.out.println("Le serveur indique qu'il n'y a rien à renvoyer pour cette commande");
}
messageRetour = null;
} catch(Exception e) {
// Gestion des exceptions en cas de problème
System.out.println("Une erreur est survenue, venez réessayer");
}
}
}
/**
* prend uneCommande dument formattée, et la traite. Dépendant du type de commande,
* elle appelle la méthode spécialisée
*/
public void traiteCommande(Commande uneCommande) throws ClassNotFoundException {
/* On distingue les différents arguments à l'aide des # */
String[] arguments_commande = uneCommande.getCommandeDesc().split("#");
/*Création d'un switch spécifiant les différentes étapes pour le traitement
de la commande...Dans l'ordre, la commande doit procéder comme cela :
Compilation - Chargement - Création - Lecture - Écriture - Appel.*/
switch(uneCommande.getCommandeDesc()){
case "Compilation":
//On utilise la commande traiterCompilation pour compiler
traiterCompilation(arguments_commande[1]);
break;
case "Chargement":
//On charge la classe via la méthode traiterChargement
traiterChargement(arguments_commande[1]);
break;
case "Création":
//On crée l'instance d'une classe
Class anyType_class = String.class;
anyType_class = Class.forName(arguments_commande[1]);
traiterCreation(anyType_class,arguments_commande[2]);
if (anyType_class == null) {
System.out.println("L'instance de la classe a échouée... veuillez réessayer");
} else {
System.out.println("L'instance de la classe a été créé avec succès");
}
break;
case "Lecture":
//On procède à la lecture
Object objLecture;
objLecture = liste_objets.get(arguments_commande[1]);
traiterLecture(objLecture, arguments_commande[2]);
break;
case "Écriture":
//On procède à l'écriture
Object objEcriture;
objEcriture = liste_objets.get(arguments_commande[1]);
traiterEcriture(objEcriture, arguments_commande[2], arguments_commande[3]);
break;
case "Appel":
//On procède à l'appel en utilisant traiteAppel()
Object pointeurObjet = liste_objets.get(arguments_commande[1]);
String[] types_values = null;
Object[] values = null;
if(arguments_commande.length>3){
String[] args = arguments_commande[3].split(",");
types_values = new String[args.length];
values = new Object[args.length];
for(int i=0; i < args.length; i++){
String[] keyValue = args[i].split(":");
types_values[i] = keyValue[0];
for (Class<?> current : liste_classes) {
if (current.getName().equals(types_values[i])) {
if(keyValue[1].contains("ID")){
values[i] = liste_objets.get(keyValue[1].substring(keyValue[1].indexOf("(")+1, keyValue[1].indexOf(")")));
}
}
}
}
}
traiterAppel(pointeurObjet, arguments_commande[2], types_values, values);
break;
}
}
/**
* traiterLecture : traite la lecture d’un attribut. Renvoies le résultat par le
* socket
*/
public void traiterLecture(Object pointeurObjet, String attribut) {
try {
Object obj;
//Création de la méthode pour l'écriture de l'attribut
Method read_method = pointeurObjet.getClass().getMethod("get" + attribut.substring(0, 1).toUpperCase() + attribut.substring(1));
/*La suite de la procédure consiste à appeler la méthode pour l'écriture de l'attribut
L'objet obj renverra le résultat de la méthode*/
obj = read_method.invoke(pointeurObjet);
/*On vérifie si la méthode a correctement été appelé ou si elle ne renvoie rien, dans ce cas
on l'informe via un message */
if(obj == null) {
System.out.println("La méthode de l'attribut : " + attribut + " a procédée avec succès, la méthode renvoie :" + obj.toString());
} else {
System.out.println("La méthode de l'attribut : " + attribut + " a échouée" );
}
} catch (Exception e) {
System.out.println("Une erreur est survenue, veuillez réessayer" + e.getMessage());
}
}
/**
* traiterEcriture : traite l’écriture d’un attribut. Confirmes au client que l’écriture
* s’est faite correctement.
*/
public void traiterEcriture(Object pointeurObjet, String attribut, Object valeur) {
try {
Object obj;
//Création de la méthode pour l'écriture de l'attribut
Method write_method = pointeurObjet.getClass().getMethod("set" + attribut.substring(0, 1).toUpperCase() + attribut.substring(1), valeur.getClass());
/*La suite de la procédure consiste à appeler la méthode pour l'écriture de l'attribut
L'objet obj renverra le résultat de la méthode*/
obj = write_method.invoke(pointeurObjet, valeur);
/*On vérifie si la méthode a correctement été appelé ou si elle ne renvoie rien, dans ce cas
on l'informe via un message */
if(obj == null) {
System.out.println("La méthode de l'attribut : " + attribut + " a procédée avec succès, la méthode renvoie :" + obj.toString() );
} else {
System.out.println("La méthode de l'attribut : " + attribut + " a échouée" );
}
} catch (Exception e) {
System.out.println("Une erreur est survenue, veuillez réessayer" + e.getMessage());
}
}
/**
5
* traiterCreation : traite la création d’un objet. Confirme au client que la création
* s’est faite correctement.
*/
public void traiterCreation(Class classeDeLobjet, String identificateur) {
try {
Object obj = classeDeLobjet.newInstance();
if(obj != null) {
System.out.println("L'objet : " + obj.toString() + " a été créé avec succès");
liste_objets.put(identificateur, obj);
} else {
System.out.println("La création de : " + obj.toString() + " a échouée");
}
} catch(Exception e){
System.out.println("Une erreur est survenue, veuillez réessayer" + e.getMessage());
}
}
/**
* traiterChargement : traite le chargement d’une classe. Confirmes au client que la création
* s’est faite correctement.
*/
public void traiterChargement(String nomQualifie) {
try {
//On identifie la classe via son nom, et on utilise un loader pour la charger
chargement_classe = Class.forName(nomQualifie);
ClassLoader classLoader = chargement_classe.getClassLoader();
//Si la classLoader renvoie null, on utilise un boostrap class load pour charger la classe
if(classLoader == null) {
Class chargement_classe2 = Class.forName("java.lang.String", true, classLoader);
System.out.println("Classe" + chargement_classe2.getName() + "a été chargé correctement");
liste_classes.add(chargement_classe2);
//Sinon, renvoyer le nom de la classe initialement chargée
} else {
System.out.println("Classe" + chargement_classe.getName() + "a été chargé correctement");
//On ajoute la classe à l'array list regroupant toutes les classes
liste_classes.add(chargement_classe);
}
} catch(Exception e) {
System.out.println("Une erreur est survenue, veuillez réessayer" + e.getMessage());
}
}
/**
* traiterCompilation : traite la compilation d’un fichier source java. Confirme au client
* que la compilation s’est faite correctement. Le fichier source est donné par son chemin
* relatif par rapport au chemin des fichiers sources.
* @param cheminRelatifFichierSource
*/
public void traiterCompilation(String cheminRelatifFichierSource) {
try{
/* Création d'un string permettant de distinguer le chemin des différents
fichiers avec un espace pour la compilation */
String[] cheminTousLesFichiers = cheminRelatifFichierSource.split(",");
// On parcourt le fichier à la recherche de tous les fichiers compilables
for (String cheminTousLesFichier : cheminTousLesFichiers) {
//Commande de compilation javac
String compilation_java = "javac" + m_rep_source + "," + cheminTousLesFichier;
//On renvoit une réponse au client pour confirmer la compilation
Runtime.getRuntime().exec(compilation_java).waitFor();
}
} catch (IOException | InterruptedException e){
System.out.println("Une erreur est survenue, veuillez réessayer : " + e.getMessage());
}
}
/**
* traiterAppel : traite l’appel d’une méthode, en prenant comme argument l’objet
* sur lequel on effectue l’appel, le nom de la fonction à appeler, un tableau de nom de
* types des arguments, et un tableau d’arguments pour la fonction. Le résultat de la
* fonction est renvoyé par le serveur au client (ou le message que tout s’est bien
* passé) */
public void traiterAppel(Object pointeurObjet, String nomFonction, String[] types,
Object[] valeurs) {
try {
ArrayList<Class> liste_type = new ArrayList<>();
//On crée une liste d'array pour stocker nos valeurs
if (types.length != 0) {
for(int i = 0; i <types.length; i++) {
//Création d'un string pour chercher le type dans la liste
String type_recherche = types[i];
liste_type.add(liste_classes.stream().filter(p->p.getName().equals(type_recherche)).findFirst().get());
}
}
//Création et appel de la méthode par la suite
Method call_method = pointeurObjet.getClass().getMethod(nomFonction,liste_type.toArray(new Class[0]));
call_method.invoke(pointeurObjet, valeurs);
System.out.println("La méthode : " + nomFonction + "a procédée avec succès");
} catch (Exception e) {
System.out.println("Une erreur est survenue, veuillez réessayer" + e.getMessage());
}
}
/**
* programme principal. Prend 4 arguments: 1) numéro de port, 2) répertoire source, 3)
* répertoire classes, et 4) nom du fichier de traces (sortie)
* Cette méthode doit créer une instance de la classe ApplicationServeur, l’initialiser
* puis appeler aVosOrdres sur cet objet
*/
public static void main(String[] args) throws Exception {
if(args.length != 4) {
System.out.println("Vous devez spécifier 4 arguments !");
} else {
int port = Integer.parseInt(args[0]);
String rep_source = args[1];
String rep_classes = args[2];
String fichSortie = args[3];
ApplicationServeur appliServeur = new ApplicationServeur(port,rep_source, rep_classes);
appliServeur.aVosOrdres();
}
}
}
Commande :
import java.io.Serializable;
/**
*
* @author Mehdi Zaaboub Ammar
* Cette classe implémente l’interface Serializable.
* Elle est utilisée pour emmagasiner la description d’une commande, selon le format spécifié ci-haut.
* Ce sont des instances de cette classe qui seront sérialisés et qui seront envoyés à travers les sockets ou RMI.
*/
public class Commande implements Serializable {
private static final long serialVersionUID = 5164651882436L;
//Correspond à la description de la commande
public String commande_desc;
//Correspond à ligne qui affichera la commande et sa description
public String commande_line = "";
//Attribuer à une description à une commande spécifique
public Commande(String commande) {
commande_desc = commande;
}
//Récupérer la description de la commande qui la caractérise
public String getCommandeDesc() {
return commande_desc;
}
//Créer le modèle de la ligne qui affichera la commande et sa description
public String lineString(){
commande_line = "La commande est : " + commande_desc ;
return commande_line;
}
}
When i run ApplicationClient, i get this:
ant -f C:\\Users\\mehdi\\OneDrive\\Documents\\NetBeansProjects\\TP1_Mehdi_8INF957 "-Dapplication.args=127.0.0.1 8080 commandes.txt sortie.txt" run
init:
deps-jar:
Updating property file: C:\Users\mehdi\OneDrive\Documents\NetBeansProjects\TP1_Mehdi_8INF957\build\built-jar.properties
Compiling 1 source file to C:\Users\mehdi\OneDrive\Documents\NetBeansProjects\TP1_Mehdi_8INF957\build\classes
compile:
run:
creation#ca.uqam.registraire.Cours#inf3123
Exception in thread "main" java.net.ConnectException: Connection refused: connect
at java.net.DualStackPlainSocketImpl.connect0(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:79)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:606)
at java.net.Socket.connect(Socket.java:555)
at java.net.Socket.<init>(Socket.java:451)
at java.net.Socket.<init>(Socket.java:261)
at ca.uqac.inf957.tp1.ApplicationClient.traiteCommande(ApplicationClient.java:88)
at ca.uqac.inf957.tp1.ApplicationClient.scenario(ApplicationClient.java:127)
at ca.uqac.inf957.tp1.ApplicationClient.main(ApplicationClient.java:148)
C:\Users\mehdi\OneDrive\Documents\NetBeansProjects\TP1_Mehdi_8INF957\nbproject\build-impl.xml:1040: The following error occurred while executing this line:
C:\Users\mehdi\OneDrive\Documents\NetBeansProjects\TP1_Mehdi_8INF957\nbproject\build-impl.xml:805: Java returned: 1
BUILD FAILED (total time: 2 seconds)
The client can't connect to the client... And ApplicationServer is take infinite time to run...and that's not normal...
Those are the arguments i tried to give to run the ApplicationClient :
127.0.0.1 8080 commandes.txt sortie.txt
I hope someone will be able to help me.
Thank you all, and have a good night.