Examen de Java

Programming · exam

Voir tous les documents en programmation

Examen de Java

Correction

FIUPSO 3/DESS – Ann´ee 2001/2002

Hugues MOUNIER

1 f´evrier 2002

Modalit´es

– Dur´ee : 4 heures

– Tous les documents sont autoris´es.

– Les sources java r´epondant `a chaque exercice, et seulement les sources seront obli-

gatoirement copi´es dans le r´epertoire examenjava (tout en minuscules) cr´ee `a 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´evelopper une application de gestion bancaire

simple en r´eseau, utilisant les sockets. Ce dernier m´ecanisme n’offrant que du transfert de

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

diff´erentier les diff´erentes op´erations bancaires tout en acheminant les donn´ees pertinentes.

Ce type de conception ne serait pas n´ecessaire si l’on prenait des invocations de m´ethodes

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

Pour r´ealiser l’objectif vis´e, on se fondera sur l’exercice de gestion bancaire en local. On

repr´esentera un paquet par une classe d´ecrite ci-dessous.

Solution de l’ex. 2 Paquets `a ´echanger

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;

Publicité

= 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];

/ 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 ´Elaboration 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

Publicité

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;

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;

Publicité

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 ´Elaboration 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,

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

Publicité

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