Examen de Java

Programming · exam

Voir tous les documents en programmation

Examen de Java

Correction

FIUPSO 3/DESS – Année 2001/2002

Hugues MOUNIER

1 février 2002

Modalités

– Durée : 4 heures

– Tous les documents sont autorisés.

– Les sources java répondant à chaque exercice, et seulement les sources seront obli-

gatoirement copiés dans le répertoire examenjava (tout en minuscules) crée à la

racine de votre compte.

Solution de l’ex. 1 Calculatrice

Voici une solution possible :

// Gestion simpliste de banque utilisant des sockets

import java.util.*;

import java.io.*;

public class Calculette {

static double resultat = 0;

/ methodes /

static int somme(int a, int b) { return(a+b); }

static int soustraction(int a, int b) { return(a-b); }

static int multiplication(int a, int b) { return(a*b); }

static double division(int a, int b) { return(a/b); }

public static void main(String args[]) {

BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

// Boucle infinie

for(;;) {

try {

// Afficher une invite a l’utilisateur

System.out.println("1 Somme de deux entiers\n" +

"2 Soustraction de deux entiers\n" +

"3 Multiplication de deux entiers\n" +

"4 Division de deux entiers\n" +

"5 Sortie du programme\n\n" +

"Veuillez entrer votre choix :\n");

// Lire une ligne entree par l’utilisateur

String line = in.readLine();

1

Examen Java

FIUPSO 3/DESS

2001/2002

entre "quit", on sort

// Si l’on rencontre une fin de fichier, ou si l’utilisateur

//

if ((line == null) || line.equals("5")) break;

// On essaie de formatter l’entree de l’utilisateur,

int choix = Integer.parseInt(line);

System.out.print("Veuillez entrer le 1er entier : ");

line = in.readLine();

int x = Integer.parseInt(line);

System.out.print("Veuillez entrer le 2eme entier : ");

line = in.readLine();

int y = Integer.parseInt(line);

switch(choix) {

case 1 : resultat = somme(x, y); // Somme

case 2 : resultat = soustraction(x, y); // Soustraction

break;

break;

case 3 : resultat = multiplication(x, y); // Multiplication

case 4 : resultat = division(x, y); // Division

break;

}

System.out.println("Resultat : " + resultat);

break;

}

// Affichage d’un message d’erreur en cas de probleme

catch(Exception e) { System.out.println("Entree Invalide"); }

}

}

}

Gestion de banque en client/serveur par sockets

L’objet des exercices qui suivent est de développer une application de gestion bancaire

simple en réseau, utilisant les sockets. Ce dernier mécanisme n’offrant que du transfert de

flux, donc d’assez bas niveau, il est nécessaire de concevoir un protocole permettant de

différentier les différentes opérations bancaires tout en acheminant les données pertinentes.

Ce type de conception ne serait pas nécessaire si l’on prenait des invocations de méthodes

distantes (RMI), bien que l’on perde évidemment en souplesse de conception.

Pour réaliser l’objectif visé, on se fondera sur l’exercice de gestion bancaire en local. On

représentera un paquet par une classe décrite ci-dessous.

Solution de l’ex. 2 Paquets à échanger

Une solution possible est la suivante :

// Gestion simpliste de banque utilisant des sockets

import java.util.*;

import java.io.*;

/**

  • Classe pour stocker les donnees d’un compte bancaire

**/

class Account {

String password;

int

Vector transactions = new Vector();

balance;

// mot de passe

// solde du compte

// historique des transactions

Hugues MOUNIER

2

Examen Java

FIUPSO 3/DESS

2001/2002

Account(String password) {

this.password = password;

this.balance = 0;

transactions.addElement("Compte ouvert le " + new Date());

}

}

/**

  • Classe representant un paquet du protocoloe bancaire

**/

public class BankSocketPacket {

String

int

String

int

name;

operation;

password;

amount;

// nom du compte

// operation bancaire

// mot de passe

// solde

/ Operations /

public static final int OPEN

public static final int CLOSE

public static final int DEPOSIT

public static final int WITHDRAW

public static final int BALANCE

public static final int QUIT

/ Erreurs /

public static final int TRANSOK

public static final int EXISTANT

public static final int NONEXISTANT = -2; // Operation sur compte inexistant

public static final int INVPASSWORD = -3; // Mot de passe invalide

public static final int NEGBALANCE

// Ouverture de compte

// Fermeture de compte

// Depot sur un compte

// Retrait sur un compte

// Solde d’un compte

// Sortie du programme

= 0;

= -1; // Overture de compte deja existant

= -4; // Solde insuffisant pour retrait

= 1;

= 2;

= 3;

= 4;

= 5;

= 6;

// Transaction bien passee

BankSocketPacket(String theName, int theOperation,

String thePassword, int theAmount) {

= theName;

name

operation = theOperation;

password = thePassword;

amount

= theAmount;

}

public String foldPacket() {

String

StringBuffer

foldedPacket;

tobeFolded = new StringBuffer();

tobeFolded.append(this.name).append(":");

Integer opCode = new Integer(this.operation);

tobeFolded.append(opCode.toString());

if (password != null) {

tobeFolded.append(":").append(this.password);

}

}

tobeFolded.append(":").append(this.amount);

tobeFolded.append("#");

foldedPacket = new String(tobeFolded);

return(foldedPacket);

public void unfoldPacket(String foldedPacket) {

Hugues MOUNIER

3

Examen Java

FIUPSO 3/DESS

2001/2002

String

unfoldedTab[] = new String[4];

Publicité

/ Le deballage est d’abord effectue dans un tableau de String /

int current = foldedPacket.indexOf(’:’, 0);

int next

int last

int i

= foldedPacket.indexOf(’:’, current+1);

= current;

= 1;

unfoldedTab[0] = foldedPacket.substring(0, current);

while (next != -1) {

unfoldedTab[i++] = foldedPacket.substring(current+1, next);

last

= current;

current = foldedPacket.indexOf(’:’, last+1);

next

= foldedPacket.indexOf(’:’, current+1);

}

unfoldedTab[i] = foldedPacket.substring(current+1, foldedPacket.length()-1);

/ On remplit les champs du paquet deballe /

try {

name = new String(unfoldedTab[0]);

operation = Integer.parseInt(unfoldedTab[1]);

password = new String(unfoldedTab[2]);

amount = Integer.parseInt(unfoldedTab[3]);

} catch (NumberFormatException e) {

System.err.println("Erreur en unfoldPacket()--parseInt() : ");

System.err.println(e);

System.exit(1);

}

}

/ Test /

/*

public static void main(String[] args) {

Account cpte = new Account("issos");

BankSocketPacket packet = new BankSocketPacket("Alexandre", cpte, OPEN);

String aAfficher = packet.foldPacket();

System.out.println(aAfficher);

String[] deballe = BankSocketPacket.unfoldPacket(aAfficher);

for(int i = 0; i < deballe.length; i++)

System.out.println(deballe[i]);

}

*/

}

Solution de l’ex. 3 Élaboration du serveur

Une solution possible est la suivante :

// Serveur Bancaire simpliste en sockets

import java.util.*;

import java.io.*;

import java.net.*;

/**

  • Cette classe implante les methodes distantes definies par l’interface
  • RemoteBank. Son plus gros defaut est que toutes les informations sur les

Hugues MOUNIER

4

Examen Java

FIUPSO 3/DESS

2001/2002

  • comptes sont perdues lorsque le serveur s’arrete.

**/

public class BankServerSocket

{

public final static int DEFAULT_PORT = 6789;

Hashtable accounts = new Hashtable();

static int transCode;

/**

  • Ouvre un compte avec le nom et le mot de passe specifie
  • Cette methode est synchronisee de facon qu’une seule thread
  • ne modifie a la fois la table des comptes.

**/

public synchronized void openAccount(String name, String password) {

// Verifier s’il exsite deja un compte ayant ce nom

if (accounts.get(name) != null) {

transCode = BankSocketPacket.EXISTANT;

return;

}

// S’il n’existe pas, le creer

Account acct = new Account(password);

// Et l’enregsitrer

accounts.put(name, acct);

transCode = BankSocketPacket.TRANSOK;

}

/**

  • Cette methode utilitaire n’est pas une methode accessible de maniere
  • distante. Etant donnes un nom et un mot de passe, verifie s’il existe
  • un compte correspondant. Si oui, renvoie l’objet Account. Sinon,
  • leve une exception.

**/

public Account verify(String name, String password) {

synchronized(accounts) {

Account acct = (Account)accounts.get(name);

if (acct == null) {

transCode = BankSocketPacket.NONEXISTANT;

return null;

}

if (!password.equals(acct.password)) {

transCode = BankSocketPacket.INVPASSWORD;

return null;

}

transCode = BankSocketPacket.TRANSOK;

return acct;

}

}

/**

  • Ferme le compte dont on donne le nom. Methode synchronisee

**/

public synchronized FunnyMoney closeAccount(String name, String password) {

Account acct;

acct = verify(name, password);

if (acct != null) {

accounts.remove(name);

synchronized (acct) {

int balance = acct.balance;

Hugues MOUNIER

5

Examen Java

FIUPSO 3/DESS

2001/2002

acct.balance = 0;

return new FunnyMoney(balance);

}

} else

return new FunnyMoney(-1);

}

/* Deposer le montant specifie su le compte dont on donne le nom /

public void deposit(String name, String password, FunnyMoney money) {

Account acct = verify(name, password);

if (acct != null)

synchronized(acct) {

acct.balance += money.amount;

acct.transactions.addElement(money.amount + " pieces deposees le "

+ new Date());

}

}

/* Effectue un retarit d’un montant specifie /

public FunnyMoney withdraw(String name, String password, int amount) {

Account acct = verify(name, password);

if (acct != null)

synchronized(acct) {

if (acct.balance < amount) {

transCode = BankSocketPacket.NEGBALANCE;

return new FunnyMoney(0);

}

acct.balance -= amount;

acct.transactions.addElement("Retrait de " + amount + " le "+new Date());

return new FunnyMoney(amount);

}

else

}

return new FunnyMoney(-1);

/* Renvoie le solde du compte dont on donne le nom /

public int getBalance(String name, String password) {

Account acct = verify(name, password);

if (acct != null)

synchronized(acct) { return acct.balance; }

else

return -1;

}

/**

  • Renvoie un vecteur de String contenant l’historique pour
  • le compte dont on donne le nom

**/

public Vector getTransactionHistory(String name, String password) {

Account acct = verify(name, password);

synchronized(acct) { return acct.transactions; }

}

void sendPacket(String name, int operation, String password, int amount,

BankSocketPacket toSend = new BankSocketPacket(name, operation, password, amount);

String lineTosend = toSend.foldPacket();

PrintStream out) {

Hugues MOUNIER

6

Examen Java

FIUPSO 3/DESS

2001/2002

out.println(lineTosend);

}

/**

  • Serveur bancaire par sockets

**/

public static void main (String[] args) throws IOException {

// no de port du service

int

String

ServerSocket

Socket

DataInputStream in;

PrintStream

out;

port;

lineRecieved = null;

server;

Publicité

client;

String

int

String

int

FunnyMoney

name;

operation;

password;

amount;

money;

// Tests d’arguments

switch(args.length) {

case 0 : port = DEFAULT_PORT;

break;

case 1 : try {

port = Integer.parseInt (args[0]);

} catch (NumberFormatException e) {

port = DEFAULT_PORT;

}

break;

default :

throw new IllegalArgumentException ("Syntaxe : java BankServerSocket [<port>]");

}

// Creation de socket serveur

System.out.println ("Demarrage sur le port " + port);

server = new ServerSocket (port);

System.out.println ("En ecoute ...");

BankServerSocket bank = new BankServerSocket();

// Boucle generale et service

while (true) {

// Acceptation de connexion

client = server.accept();

System.out.println ("Connexion a " + client.getInetAddress() + " acceptee");

System.out.flush();

// Capture des flux de reception et d’envoi

in = new DataInputStream(client.getInputStream());

out = new PrintStream(client.getOutputStream());

//-----------------------

// TRAITEMENT DU SERVICE

//-----------------------

while (true) {

// lire une ligne

lineRecieved = in.readLine();

if ((lineRecieved == null))

break;

Hugues MOUNIER

7

Examen Java

FIUPSO 3/DESS

2001/2002

BankSocketPacket toUnfold = new BankSocketPacket(null, 0, null, 0);

toUnfold.unfoldPacket(lineRecieved);

= toUnfold.name;

name

operation = toUnfold.operation;

password = toUnfold.password;

amount

= toUnfold.amount;

switch(operation) {

case BankSocketPacket.OPEN :

bank.openAccount(name, password);

bank.sendPacket("noname", transCode, "nopass", 0, out);

break;

case BankSocketPacket.CLOSE :

money = bank.closeAccount(name, password);

bank.sendPacket(name, transCode, password, money.amount, out);

break;

case BankSocketPacket.DEPOSIT :

money = new FunnyMoney(amount);

bank.deposit(name, password, money);

bank.sendPacket(name, transCode, password, money.amount, out);

break;

case BankSocketPacket.WITHDRAW :

money = bank.withdraw(name, password, amount);

bank.sendPacket(name, transCode, password, money.amount, out);

break;

case BankSocketPacket.BALANCE :

int amt = bank.getBalance(name, password);

bank.sendPacket(name, transCode, password, amt, out);

break;

case BankSocketPacket.QUIT :

System.out.println ("Fermeture des socket client & serveur");

client.close ();

server.close ();

System.exit(0);

}

}

if (lineRecieved == null) {

// Sortie du service : le client a termine

System.out.println ("Fermeture de socket client");

client.close ();

}

}// while(true)

}/ main() /

}// BankServerSocket

/*

try {

}

catch (Exception e) {

System.err.println(e);

System.err.println("Utilisation : java BankServerSocket");

System.exit(1); // On sort

}

Hugues MOUNIER

8

Examen Java

FIUPSO 3/DESS

2001/2002

*/

Solution de l’ex. 4 Élaboration du client

Une solution possible est la suivante :

// Gestion simpliste de banque en sockets : client

// Historique a terminer ??

import java.util.*;

import java.io.*;

import java.net.*;

/**

  • Classes conteneur :
  • - FunnyMoney

**/

la monnaie utilisee

/**

  • Cette classe simple represente un montant monetaire. N’est qu’un emballage
  • d’un entier.

**/

class FunnyMoney {

public int amount;

public FunnyMoney(int amount) { this.amount = amount; }

}

/**

  • Client simple interagissant avec un serveur

**/

public class BankSocket {

// Variables de classe constantes : port et machine par defaut

public static final int

public static final String DEFAULT_HOST = "localhost";

DEFAULT_PORT = 6789;

// Methode utilitaire de saisie

public static String getName(BufferedReader in) {

String name = null;

try {

System.out.println("Veuillez entrer le nom du compte : ");

name = new String(in.readLine().toLowerCase());

} catch (IOException e) {

System.err.println("Erreur en readLine()");

}

return name;

}

// Methode utilitaire de saisie

public static String getPassword(BufferedReader in) {

String password = null;

try {

System.out.println("Veuillez entrer le mot de passe : ");

Hugues MOUNIER

9

Examen Java

FIUPSO 3/DESS

2001/2002

password = new String(in.readLine().toLowerCase());

} catch (IOException e) {

System.err.println("Erreur en readLine()");

}

return password;

}

// Methode utilitaire de gestion d’erreur

static void treatError(int errorNb) {

switch(errorNb) {

case BankSocketPacket.EXISTANT

:

System.out.println("Le compte existe deja");

break;

case BankSocketPacket.NONEXISTANT :

System.out.println("Compte inexistant");

break;

case BankSocketPacket.INVPASSWORD :

System.out.println("Mot de passe invalide");

break;

case BankSocketPacket.NEGBALANCE

:

System.out.println("Solde insuffisant");

break;

}

}

// Methode utilitaire d’envoi/reception de paquet

static BankSocketPacket sendReceive(BankSocketPacket toSend,

Publicité

BankSocketPacket unfolded = new BankSocketPacket(null, 0, null, 0);

DataInputStream sin, PrintStream sout, String message) {

String lineTosend = toSend.foldPacket();

sout.println(lineTosend);

try {

String lineRecieved = sin.readLine();

if (lineRecieved != null) {

unfolded.unfoldPacket(lineRecieved);

if (unfolded.operation == BankSocketPacket.TRANSOK)

System.out.println(message);

else

treatError(unfolded.operation);

} else {

}

System.out.println("Serveur arrete ; sortie");

System.exit(1);

} catch (IOException e) {

System.out.println("Erreur en reception de paquet : " +

e.toString());

System.exit(1);

}

return(unfolded);

}

/**

  • Programme client

**/

public static void main(String[] args) {

Hugues MOUNIER

10

Examen Java

FIUPSO 3/DESS

2001/2002

try {

port;

= null; // Machine du serveur

String host

int

Socket s

= null;

DataInputStream sin = null;

PrintStream sout

= null;

BufferedReader stdin = null;// Flux associe au clavier

// No de port du serveur (no de service)

// Reference a la socket client

// Flux en provenance du serveur

// Flux a destination du serveur

//

BankSocket b = new BankSocket();

// Tests d’arguments

switch(args.length) {

case 0 : host = new String(DEFAULT_HOST);

port = DEFAULT_PORT;

break;

case 1 : host = new String(args[0]);

port = DEFAULT_PORT;

break;

case 2 : host = new String(args[0]);

try {

port = Integer.parseInt (args[1]);

} catch (NumberFormatException e) {

System.err.println("Numero de port invalide. " +

DEFAULT_PORT + " Utilise.");

port = DEFAULT_PORT;

}

break;

default : System.out.println("Nombre d’arguments illegal");

throw new IllegalArgumentException();

}// switch()

s = new Socket(host, port);

// Creer les flux pour lire et ecrire des lignes de texte

// de et vers cette socket.

sin = new DataInputStream(s.getInputStream());

sout = new PrintStream(s.getOutputStream());

System.out.println("Connecte a " + s.getInetAddress()

+ ":"+ s.getPort());

(par defaut le clavier)

// Creer un flux pour lire des lignes de l’entree standard

//

stdin = new BufferedReader(new InputStreamReader(System.in));

String cmd = "nothing";

while(true) {

System.out.println("\nVeuillez entrer une commande : \n" +

(ouverture de compte)\n" +

(cloture de compte)\n" +

"open

"close

"deposit (depot sur le compte)\n" +

"withdraw (retrait sur le compte)\n" +

"balance (solde du compte)\n" +

"quit

(sortie du programme)\n");

// Convertir la commande utilisateur en minuscules

cmd = stdin.readLine().toLowerCase();

// Differentes actions possibles

if (cmd.equals("open")) {

// ouverture de compte

String name = getName(stdin); String password = getPassword(stdin);

BankSocketPacket packet =

Hugues MOUNIER

11

Examen Java

FIUPSO 3/DESS

2001/2002

new BankSocketPacket(name, BankSocketPacket.OPEN, password, 0);

BankSocketPacket unfolded = sendReceive(packet, sin, sout, "Compte ouvert.");

}

else if (cmd.equals("close")) {

String name = getName(stdin);

BankSocketPacket packet =

// fermeture de compte

String password = getPassword(stdin);

new BankSocketPacket(name, BankSocketPacket.CLOSE, password, -1);

BankSocketPacket unfolded = sendReceive(packet, sin, sout, "Solde : ");

System.out.println(unfolded.amount + " pieces rendues.");

System.out.println("Au revoir.");

}

else if (cmd.equals("deposit")) {

String name = getName(stdin);

System.out.println("Veuillez entrer le montant : ");

int amount = Integer.parseInt(stdin.readLine().toLowerCase());

BankSocketPacket packet =

// depot d’argent

String password = getPassword(stdin);

new BankSocketPacket(name, BankSocketPacket.DEPOSIT, password, amount);

BankSocketPacket unfolded = sendReceive(packet, sin, sout, "Depot realise.");

}

else if (cmd.equals("withdraw")) {

// retrait d’argent

String name = getName(stdin); String password = getPassword(stdin);

System.out.println("Veuillez entrer le montant : ");

int amount = Integer.parseInt(stdin.readLine().toLowerCase());

BankSocketPacket packet =

new BankSocketPacket(name, BankSocketPacket.WITHDRAW, password, amount);

BankSocketPacket unfolded = sendReceive(packet, sin, sout, "Retrait realise.");

}

else if (cmd.equals("balance")) {

// solde du compte

String name = getName(stdin); String password = getPassword(stdin);

BankSocketPacket packet =

new BankSocketPacket(name, BankSocketPacket.BALANCE, password, -1);

BankSocketPacket unfolded = sendReceive(packet, sin, sout, "Solde : ");

System.out.println(unfolded.amount + " pieces sur le compte.");

//

//

//

//

}

else if (cmd.equals("history")) {

String name = getName(stdin);

Vector transactions = bank.getTransactionHistory(name, password);

for(int i = 0; i < transactions.size(); i++)

// historique des transactions

String password = getPassword(stdin);

System.out.println(transactions.elementAt(i));

}

else if (cmd.equals("quit")) {

BankSocketPacket packet =

// break

new BankSocketPacket("noname", BankSocketPacket.QUIT, "nopass", -1);

BankSocketPacket unfolded = sendReceive(packet, sin, sout, "Solde : ");

System.out.println("Au revoir\n");

break;

}

else System.out.println("Action inconnue");

}

}// while not quitted

// Exceptions, erreurs de syntaxe, affichage d’utilisation

catch (Exception e) {

System.err.println(e);

System.err.println("Utilisation : java BankLocal");

}

}

}// class Client

Hugues MOUNIER

12

Examen Java

FIUPSO 3/DESS

2001/2002

Hugues MOUNIER

13