Documente Academic
Documente Profesional
Documente Cultură
Structures de donnes
Notions en Gnie Logiciel
et Programmation Oriente Objet
H. Mounier
Universit Paris Sud
II
Threads
I.1
Modle de threads de Java . . . . . . .
I.2
Cration et utilitaires . . . . . . . . . .
I.3
Synchronisation . . . . . . . . . . . . .
I.4
Groupes de threads . . . . . . . . . . .
I.5
tats dune thread et ordonnancement
.
.
.
.
.
1
1
3
7
15
20
25
25
32
39
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
spcifiquement Awt
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
49
49
56
63
71
.
.
.
.
.
.
.
85
85
90
93
95
103
106
108
Classe Url
111
V.1
Classe URL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
i
ii
VI Paquetage java.net : Sockets
VI.1 Sockets : Rappels TCP/IP .
VI.2 Sockets : Clients . . . . . . .
VI.3 Sockets serveurs . . . . . . .
VI.4 Serveurs itratifs . . . . . .
VI.5 Serveurs non bloquants . . .
VI.6 Serveurs concurrents . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
115
115
116
125
128
130
132
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
135
135
136
138
140
144
148
149
Bibliographie
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
151
I Threads
Rfrences bibliographiques
The Java Language Specification, J. Gosling, B. Joy et G. Steele [GJS96],
Java Threads, S. Oaks et J. Wong [OW97],
Concurrent Programming in Java. Design Principles and Patterns, D. Lea
[Lea97].
I.1
1.4 Synchronisation
Synchronisation inter-threads via des moniteurs. Notion dfinie par C.A.R
Hoare.
Moniteur : mini bote ne pouvant contenir quune thread. Une fois quune
thread y est entre, les autres doivent attendre quelle en sorte.
Pas de classe Monitor. Chaque objet a son propre moniteur implicite
dans lequel on entre automatiquement lorsquune mthode synchronise de
(linstance de) lobjet est appele.
Lorsquune thread est dans une mthode synchronise, aucune autre thread
ne peut appeler de mthode synchronise de la mme instance de lobjet.
Permet un code clair et compact, la synchronisation tant construite dans
le langage.
Il est galement possible pour 2 threads de communiquer par un mcanisme
simple et souple.
I.2
Cration et utilitaires
getName()
getPriority()
isAlive()
join()
resume()
run()
sleep()
start()
suspend()
But
Obtenir le nom dune thread
Obtenir la priorit dune thread
Dterminer si une thread est toujours en
cours dexcution
Attendre la terminaison dune thread
Poursuivre lexcution dune thread suspendue
Point dentre (dexcution) de la thread
Suspendre la thread pour une priode de
temps donne
Dbuter une thread en appelant sa mthode run()
Suspendre une thread
Thread.sleep(1000);
}
} catch (InterruptedException e) {
System.out.println("Parent interrompu.);
}
System.out.println("Sortie de lactivite parent");
}// run()
}// class Activite
}
} catch (InterruptedException e) {
System.out.println("Parent interrompu.);
}
System.out.println("Sortie de lactivite parent");
}// run()
}// class Activite
qui suspend lexcution de la thread appelante pendant millisec milisecondes. Elle peut dclencher une exception
Pour obtenir et changer le nom dune thread, on dispose de :
final void setName(String nomThread)
final String getName()
I.3 Synchronisation
I.3
Synchronisation
3.1 Synchronisation
Lorsque 2 threads ou plus ont besoin dune mme ressource au mme moment, il y a besoin de sassurer que la ressource ne sera utilise que par une
thread en mme temps : on utilise alors un procd de synchronistaion.
Un moyen dobtenir une synchronisation : les moniteurs.
Un moniteur est un mcanisme utilis comme un verrou dexclusion mutuelle, un mutex.
Lorsquune thread acquiert un verrou, on dit quelle entre dans le moniteur.
Les autres threads sont dites en attente du moniteur.
Analogie avec des cabines dessayage de vtements.
Deux moyens de synchronisation : les mthodes synchronises et les blocs
synchroniss.
I.3 Synchronisation
10
// bloc synchronise
class Synch {
public static void main(String args[]) {
Callme cible = new Callme();
Caller activ1 = new Caller(cible, "Bonjour");
Caller activ2 = new Caller(cible, "monde");
Caller activ1 = new Caller(cible, "synchronise");
// On attend que les activites se terminent
try {
activ1.th.join();
activ2.th.join();
activ3.th.join();
} catch(InterruptedException e) {
System.out.println("Interrompue");
}
I.3 Synchronisation
11
}
}// class Synch
Il y a galement la forme final void wait(long timeout) qui permet dattendre un nombre donn de millisecondes.
Exemple dimplantation incorrecte dune forme simple du problme producteur/consommateur.
Il y a 4 classes :
La classe FileAttente, la file dont on veut synchroniser les accs ;
La classe Producteur, lobjet thread qui produit les entres de la file ;
La classe Consommateur qui les consomme ;
La classe ProdCons, la classe qui cre la file, le producteur et le consommateur.
12
I.3 Synchronisation
13
}
}
} // class Consommateur
class ProdCons {
public static void main(String args[]) {
FileAttente f = new FileAttente();
new Producteur(f);
new Consommateur(f);
System.out.println("Ctrl-C pour arreter.");
}// class ProdCons
14
15
f.prendre();
}
}
} // class Consommateur
class ProdCons {
public static void main(String args[]) {
FileAttente f = new FileAttente();
new Producteur(f);
new Consommateur(f);
System.out.println("Ctrl-C pour arreter.");
}// class ProdCons
I.4
Groupes de threads
16
But
void destroy()
static int enumerate(Thread
group[])
static int enumerate(Thread
group[], boolean all)
17
Renvoie le nombre de threads dans le
groupe, plus le nombre de groupe dont
cette thread est le parent.
Renvoie le nombre de groupe dont cette
thread est le parent.
Provoque la vrification par le gestionnaire
de scurit du fait que la thread appelante
peut eccder et/ou changer le groupe partir duquel checkAccess() est appel.
Dtruit le groupe de threads (et tous les
enfants) partir duquel lappel est effectu.
Les threads constituant le groupe appelant
sont stockes dans le tableau group.
Les threads constituant le groupe appelant
sont stockes dans le tableau group. Si all
est true, les threads de tous les sous
groupes de la thread appelante sont galement stocks dans group.
Les threads constituant le groupe appelant
sont stockes dans le tableau group.
Les threads constituant le groupe appelant sont stockes dans le tableau group.
Si all est true, les sous groupes de
tous les sous groupes (et ainsi de suite) de
la thread appelante sont galement stocks
dans group.
Renvoie la plus haute priorit dun membre
du groupe.
Renvoie le nom du groupe.
Renvoie null si le ThreadGroup appelant
na pas de parent. Sinon, renvoie le parent
de lobjet invoqu.
Renvoie true si le groupe est un groupe
de dmons. Sinon, renvoie false.
Affiche des informations sur le groupe.
Renvoie true si la thread appelante est
le parent de group (ou group lui-mme).
Sinon, renvoie false.
Fait reprendre lexcution toutes les
threads du groupe appelant.
Si isDaemon est gal true, le groupe
appelant est tiquet comme un groupe de
dmons.
18
class ThreadLister {
// Afficher des informations a propos dune activite
private static void print_thread_info(PrintStream out, Thread t,
19
String indent) {
if (t == null) return;
out.println(indent + "Activite : " + t.getName() +
" Priorite : " + t.getPriority() +
(t.isDaemon()?" Demon":"") +
(t.isAlive()?"":" Non vivante"));
}
// Afficher des informations a propos dun groupe dactivite, de
//
ses activites et groupes
private static void list_group(PrintStream out, ThreadGroup g,
String indent) {
if (g == null) return;
int num_threads = g.activeCount();
int num_groups = g.activeGroupCount();
Thread[] threads = new Thread[num_threads];
ThreadGroup[] groups = new ThreadGroup[num_groups];
g.enumerate(threads, false);
g.enumerate(groups, false);
out.println(indent + "Groupe dactivites : " + g.getName() +
" Priorite max : " + g.getMaxPriority() +
(g.isDaemon()?" Demon":""));
for(int i = 0; i < num_threads; i++)
print_thread_info(out, threads[i], indent + "
for(int i = 0; i < num_groups; i++)
list_group(out, groups[i], indent + "
");
");
}
// Trouver la racine du groupe dactivites et lister recursivement
public static void listAllThreads(PrintStream out) {
ThreadGroup current_thread_group;
ThreadGroup root_thread_group;
ThreadGroup parent;
// Obtenir le groupe dactivites courant
current_thread_group = Thread.currentThread().getThreadGroup();
// Aller chercher la racine des groupes dactivites
root_thread_group = current_thread_group;
parent = root_thread_group.getParent();
20
I.5
21
22
tat
actuel
prt
nouveau
prt
start()
en cours2
quantum
puis,
en
cours
suspendu bloqu
lu1
suspend()
suspend()
yield()
suspendu- mort
bloqu
stop()
sur E/S,
sleep(),
wait(),
stop()
run()
termin
join()
suspendu
bloqu
resume()
stop()
E/S termine,
sleep() expire,
notify(),
notifyAll(),
suspend()
stop()
join()
termin
suspendubloqu
E/S termine
resume()
stop()
5.3 Ordonnancement
Lordonnaceur sassure que la thread de plus haute priorit (ou les sil y en
a plusieurs dgale priorit) est excute par la CPU.
Si une thread de plus haute priorit entre dans la file des threads prtes,
lordonnanceur de threads Java met la thread en cours dans la file dattente,
pour que la prioritaire sexcute.
La thread en cours est dite supplante par premption par la thread de plus
haute priorit.
Si la thread en cours dexcution passe la main (via yield(), est suspendue
ou bloque, lordonnanceur choisit dans la file dattente prte la thread de
priorit la plus leve (ou lune dentre elles si elles sont plusieurs) pour tre
excute.
Un autre aspect est le partage du temps (time slicing). Un ordre de grandeur
courant pour un quantum de temps est 100ms. En temps partag, si une
thread en cours dexcution na pas t stoppe, bloque, suspendue, ne
sest pas termine, ou na pas pass la main, et sil y a dautres threads
de priorit gale dans la file dattente prte, la CPU est ralloue lune
dentre elles.
Sous Solaris 2.x, la version 1.1 du JDK neffectue pas de partage de temps
entre les threads : une thread sexcute jusqu ce quelle se termine,
1
2
(par lordonnanceur)
(dexcution)
23
II.1
26
package DataStructures;
import Exceptions.*;
//
//
//
//
//
//
//
//
//
//
//
Stack interface
****************** OPERATIONS PUBLIQUES *************************
void push( x )
--> Inserer x
void pop( )
--> Enlever lelt insere le + recemment
Object top( )
--> Renvoyer lelt insere le + recemment
Object topAndPop( )
--> Renvoyer et enlever lelt le + receent
boolean isEmpty( )
--> Renvoyer true si vide; false sinon
void makeEmpty( )
--> Enlever tous les elements
****************** ERREURS **************************************
top, pop, ou topAndPop sur une pile vide
/**
* Protocole pour piles
*/
public interface Stack
{
/**
* Tester si la pile est logiquement vide
* @return true si vide, false sinon.
*/
boolean isEmpty( );
/**
* Prendre lelement insere le plus recemment sur la pile.
* naltere pas la pile.
* @return lelement le plus recemment insere dans la pile
* @exception Underflow si la pile est vide
*/
Object top( )
throws Underflow;
/**
* Enleve lelement insere le plus recemment sur la pile
* @exception Underflow si la pile est vide
*/
void
pop( )
throws Underflow;
/**
27
// StackAr class
//
// CONSTRUCTION : sans constructeur
//
//
//
//
//
//
//
//
//
//
28
/**
* Implantation dune pile a partir dun tableau
*/
public class StackAr implements Stack
{
/**
* Construire la pile
*/
public StackAr( )
{
theArray = new Object[ DEFAULT_CAPACITY ];
topOfStack = -1;
}
29
30
/**
* Implantation dune pile sur une liste
*/
public class StackLi implements Stack
{
/**
* Construire la pile
31
32
II.2
33
sortie
transformerDonnees()
34
35
En crivant une mthode utilitaire, on doit essayer de ne prendre des entres que
des paramtres et neffectuer de sorties quau travers de paramtres, de valeurs
de retour ou dexceptions.
ounces
valeur de retour
convertOzToMl()
Si cest le cas, vous pourriez tre tent dcrire convertOzToMl() comme suit :
class Liquid {
private static final double FL_OUNCES_PER_ML = 12.0/355.0;
private static final double ML_PER_FL_OUNCE = 355.0/12.0;
36
amount
cup
convertOzToMl()
37
Lutilisation de cette version ncessite de connatre pas mal de dtails internes dimplantation de la mthode.
Par contraste, dans une bonne mthode utilitaire, le programmeur qui sen
sert peut comprendre comment lutiliser simplement en regardant la
signature de la mthode et son type de retour (ce qui est spcifi
dans une interface).
De plus, la variable q, si elle est utilise ailleurs, peut provoquer des effets
de bords trs gnants.
38
39
II.3
40
2/ Les mthodes cohsives rendent votre code plus facile changer lorsque
chaque mthode effectue une seule tche bien dfinie. On dispose de
briques de base lmentaires laide desquelles on peut contruire telle
ou telle architecture logicielle. De plus, les changements de comportement que lon peut tre amen faire au sein dune mthode seront plus
isols si ce comportement est emball dans sa propre mthode
41
La mthode modify() est peu cohsive parce quelle inclus du code pour
effectuer des actions qui sont conceptuellement assez diffrentes
Elle est difficile comprendre en partie parce que son nom, modify(), nest
pas trs spcialis
Une autre raison pour laquelle elle est difficile comprendre est que certaines
donnes qui lui sont passes ou quelle renvoie ne sont utilises que dans
certains cas.
Par exemple, si action est gal CoffeCup.ADD, la valeur de retour de
la mthode est sans signification
De mme, si si action est gal CoffeCup.SPILL, le paramtre dentre
amount est inutilis.
Si lon ne regarde qu la signature de la mthode et sa valeur de retour,
il nest pas clair de deviner ce que la mthode va faire.
42
action
valeur de retour
modify()
43
if (all) {
int allCoffee = innerCoffee;
innerCoffee = 0;
returnValue = allCoffee;
}
else {
// remove the amount of coffee passed as amount
int sip = amount;
if (innerCoffee < amount) {
sip = innerCoffee;
}
innerCoffee -= sip;
returnValue = sip;
}
return returnValue;
}
}
Cette solution est meilleure, mais pas encore optimale. La mthode add()
na pas besoin de paramtres de contrle, mais remove() en a besoin.
amount
valeur de retour
all
remove()
44
Donc, au lieu dexprimer ses souhaits au travers dun paramtre supplmentaire, on appelle une mthode supplmentaire. Par exemple, au lieu de
faire
class Example1 {
public static void main(String[] args) {
CoffeeCup cup = new CoffeeCup();
// ignorer la valeur de retour erronnee de modify()
//
dans le case ADD
cup.modify(CoffeeCup.ADD, 355);
int mlCoffee = cup.modify(CoffeeCup.RELEASE_SIP, 25);
// 2ieme parametre inutilise dans le case SPILL
mlCoffee += cup.modify(CoffeeCup.SPILL, 0);
System.out.println("Ml of coffee: " + mlCoffee);
}
}
on fera
class Example3 {
public static void main(String[] args) {
45
46
47
III.1
Exemple 1 : balles
1.1 BallWorld
import java.awt.*;
import java.awt.event.*;
public class BallWorld extends Frame {
public static void main (String [ ] args)
{
BallWorld world = new BallWorld (Color.red);
world.show ();
}
49
50
//
//
//
//
7
8
9
10
//
//
//
//
//
11
12
13
14
15
//
//
//
//
16
17
18
19
}
public void paint (Graphics g) {
// dabord, afficher la balle
aBall.paint (g);
// puis la bouger legeremenet
aBall.move();
// et traiter les cas de debordement
if ((aBall.x() < 0) || (aBall.x() > FrameWidth))
aBall.setMotion (-aBall.xMotion(), aBall.yMotion());
if ((aBall.y() < 0) || (aBall.y() > FrameHeight))
aBall.setMotion (aBall.xMotion(), -aBall.yMotion());
// enfin, reafficher le cadre
counter = counter + 1;
if (counter < 2000) repaint();
else System.exit(0);
}
}
51
methode()
setCursor(int cursorType)
setIconImage(Image image)
setMenuBar(MenuBar mb)
setResizable(boolean resizable)
setTitle(String title)
dispose()
But
choisit le type de curseur
choisit licne
choisit le menu
peut changer de taille ou pas
choisit le titre
redfinition de Window.dispose()
52
import java.awt.*;
public class Ball
protected
protected
protected
protected
{
Rectangle location;
double dx;
double dy;
Color color;
53
{
location = new Rectangle(x-r, y-r, 2*r, 2*r);
dx = 0;
dy = 0;
color = Color.blue;
}
// fonctions fixant les attributs
//
public void setColor (Color newColor)
{ color = newColor;
{ return dx; }
{ return dy; }
{ return location; }
54
FrameWidth
FrameHeight
ballArray;
BallArraySize
counter
= 600;
= 400;
= 6;
= 0;
55
56
III.2
Exemple 2 : Flipper
57
Pulieurs balles, nombre inconnu lavance utilisation de Vector : tableau croissance dynamique
Pas besoin de spcifier le type des lments dun vecteur
Un vecteur contient des Object les types primitifs ( int, . . . ) doivent
tre convertis en leurs objets associs ( Integer, . . . ) Accs un lment
doit tre suivi dun cast : Ball aBall = (Ball) balls.elementAt(i) ;
Interface java : description de comportement. Pas dimplantation de mthode. Seuls champs de donnes permis dclars static
Hritage : un enfant hrite de la structure de ses parents et de la possibilit
dimiter le comportement des parents.
Interface : pas de corps de mthode dans une interface parent Une classe
enfant hrite seulement de la spcification des mthodes et non de
la structure (champs de donnes, corps de mthodes)
Une interface peut tre utilise comme type de donnes. La variable
doit tre une instance de classe implantant linterface
Une classe implantant une interface doit fournir le corps de toutes les mthodes adaptateurs : classes implantant linterface avec toutes les mthodes corps vide : {}
Exemple dadaptateur pour les couteurs souris (interface MouseListener) :
classe MouseAdapter
Lutilisateur dfinit une classe hritant de MouseAdapter avec une redfinition des seules mthodes ncessaires.
Ici, seule mousePressed() est redfinie, dans la classe MouseKeeper.
private class MouseKeeper extends MouseAdapter {
public void mousePressed (MouseEvent e) {
58
59
60
Lorsquune boule qui descend entre en contact avec lui, le Spring fait
rebondir la balle.
Il est reprsent par un rectangle (aplati) et une srie de segments en
61
zigzag
Il y a intersection ressort-boule si le rectangle aplati du ressort et celui
circonscrit la boule sintersectent
2 reprsentations graphiques du ressort, contrl par state :
tat comprim ( state == 1) : tat de dpart
tat dtendu ( state == 2) : dclench par le choc dune boule (dans
hitBy())
62
63
III.3
Formes dhritage
3.1 Hritages
En Java, lhritage stricto sensu (mot cl extends) est la sous classification.
Toutefois, beaucoup de points communs entre lhritage de spcification (mot cl implements) et la sous classification, ou hritage de code.
Hritage :
le comportement et les donnes des classes enfants sont une extension des proprits des classes parents (mot cl extends).
Mais galement :
une classe enfant est une version plus spcialise (ou restreinte)
dune classe parent ; cest donc galement une contraction dune
classe parent.
Exemple : un Frame est tout type de fentre, mais un PinBallGame est un
type bien de fentre particulier.
Les Extension/Contraction donnent plusieurs usages de lhritage.
64
methode()
But
equals(Object obj)
getClass()
hashCode()
toString()
3.3 Substituabilit
Substituabilit : le type donn lors de la dclaration dune variable peut
diffrer de celui de linstance rfrence par la variable.
Exemple : dans le jeu de flipper, la variable target est dclare comme
PinBallTarget, mais correspond beuacoup de cibles diffrentes (du vecteur
targets) PinBallTarget target = (PinBallTarget) target.elementAt(j) ;
Une variable dclare de type Object peut contenir (rfrencer une instance
de) tout type non primitif. Un vecteur contient des lments de type Object ;
on peut donc tout y stocker.
Une justification possible de la substituabilit par hritage est le
principe de substitution
(i) les instances de la sous classe doivent possder tous les champs
de donnes associs la classe parent ;
(ii) les instances de la sous classe doivent implanter, au moins par hritage, toutes les fonctionnalits dfinies pour la classe parent ;
(iii) donc une instance dune classe enfant peut imiter le comportement
dune classe parent et tre indistinguable dune instance de la
classe parent lorsque substitue dans une situation similaire.
Ceci ne couvre pas toutes les utilisations de lhritage.
65
66
Les mthodes dclares abstract doivent tre redfinies dans une sousclasse instanciable.
Hritage par spcification : la classe parent nimplante pas le comportement
mais dfinit celui qui doit tre implant dans les classes enfant.
67
Forme dhritage parfois boude, parce que violant directement le principe de substitution.
Forme toutefois pratique et assez largement utilise.
68
...
Ensuite, une classe peut implanter plus dune interface. Par exemple,
dans la bibliothque dE/S Java, un RandomAcessFile implante la fois les
protocoles DataInput et DataOutput.
69
3.12 Modificateurs
Plusieurs modificateurs peuvent altrer divers aspects du processus dhritage.
Modificateurs de visibilit (ou de contrle daccs) : public, protected,
private
Modificateurs daccessibilit :
static : on ne peut redfinir une mthode static
abstract : classes non instanciables ; ne peut tre utilis que comme type
parent.
final : linverse du prcdent. On ne peut crer de sous classe dune
classe final.
70
71
III.4
W.A. Wulf A case Against the GOTO, Proc. of the 25th National ACM Conf., 1972.
72
73
...
public void draw (Graphics g, int x, int y) {
String names[] = {"A", "2", "3", "4", "5", "6",
"7", "8", "9", "10", "J", "Q", "K"};
// effacer le rectangle et dessiner le contour
g.clearRect(x, y, width, height);
g.setColor(Color.blue);
g.drawRect(x, y, width, height);
// dessiner le corps de la carte
g.setColor(color());
if (faceUp()) {
g.drawString(names[rank()], x+3, y+15);
if (suit() == heart) {
g.drawLine(x+25, y+30, x+35, y+20);
g.drawLine(x+35, y+20, x+45, y+30);
g.drawLine(x+45, y+30, x+25, y+60);
g.drawLine(x+25, y+60, x+5, y+30);
g.drawLine(x+5, y+30, x+15, y+20);
g.drawLine(x+15, y+20, x+25, y+30);
}
else if (suit() == spade) {
g.drawLine(x+25, y+20, x+40, y+50);
g.drawLine(x+40, y+50, x+10, y+50);
g.drawLine(x+10, y+50, x+25, y+20);
g.drawLine(x+23, y+45, x+20, y+60);
g.drawLine(x+20, y+60, x+30, y+60);
g.drawLine(x+30, y+60, x+27, y+45);
}
else if (suit() == diamond) {
g.drawLine(x+25, y+20, x+40, y+40);
g.drawLine(x+40, y+40, x+25, y+60);
g.drawLine(x+25, y+60, x+10, y+40);
g.drawLine(x+10, y+40, x+25, y+20);
}
else if (suit() == club) {
g.drawOval(x+20, y+25, 10, 10);
g.drawOval(x+25, y+35, 10, 10);
g.drawOval(x+15, y+35, 10, 10);
g.drawLine(x+23, y+45, x+20, y+55);
g.drawLine(x+20, y+55, x+30, y+55);
g.drawLine(x+30, y+55, x+27, y+45);
}
}
74
x+15,
x+35,
x+45,
x+45,
x+45,
y+65);
y+65);
y+20);
y+35);
y+50);
A.H. Morehead et G. Mott-Smith, The Complete Book of Solitaire and Patience Games,
Grosset & Dunlap, New York, 1949.
75
76
77
X
X
X
X
X
SuitPile
DeckPile
DiscardPile
TablePile
X
X
X
X
X
X
X
78
4.5 La pioche
class DeckPile extends CardPile {
DeckPile (int x, int y) {
// Initialiser le parent
super(x, y);
// Puis creer la pioche
// que lon place dabord dans une pile locale
for (int i = 0; i < 4; i++)
for (int j = 0; j <= 12; j++)
addCard(new Card(i, j));
// Ensuite, on bat les cartes
Random generator = new Random();
for (int i = 0; i < 52; i++) {
int j = Math.abs(generator.nextInt() % 52);
// Echanger 2 valeurs de cartes
Object temp = thePile.elementAt(i);
thePile.setElementAt(thePile.elementAt(j), i);
thePile.setElementAt(temp, j);
}
}
public void select(int tx, int ty) {
if (isEmpty())
return;
Solitare.discardPile.addCard(pop());
}
}
Lorsque construite, la pioche cre le jeu complet des 52 cartes. Une fois cr,
le jeu est mlang. Un gnrateur de nombres pseudo-alatoires est dabord
cr, puis chaque carte est change avec une, prise au hasard.
On ralise un accs altoire dans une pile. Logiquement, on veut restreindre laccs au seul lment du dessus. En Java, une Stack est construite
par hritage partir dun Vector. Donc la mthode elementAt() peut tre
applique une Stack. Cest un exemple dhritage par construction.
select() ne fait rien si la pioche est vide. Sinon, la carte du dessus est
enleve et ajoute la pile de dfausse.
Une variable static par pile est utilise. Ici, on se sert de Solitaire.discardPile.
79
80
81
Solitare.suitPile[i].addCard(topCard);
return;
}
82
DiscardPile discardPile;
TablePile tableau [ ];
SuitPile suitPile [ ];
CardPile allPiles [ ];
window;
83
public void
int
int
for
mousePressed (MouseEvent e) {
x = e.getX();
y = e.getY();
(int i = 0; i < 13; i++)
if (allPiles[i].includes(x, y)) {
allPiles[i].select(x, y);
repaint();
}
}
}
public SolitareFrame() {
setSize(600, 500);
setTitle("Solitaire Game");
addMouseListener (new MouseKeeper());
Button restartButton = new Button("New Game");
restartButton.addActionListener(new RestartButtonListener());
add("South", restartButton);
}
public void paint(Graphics g) {
for (int i = 0; i < 13; i++)
allPiles[i].display(g);
}
}
}
Constructeur :
cration dune fentre, SolitaireFrame,
appel de init(),
affichage de la fentre
init() ralise linitialisation des piles dclares static.
Notez : 3 oprations distinctes pour un tableau : dclaration, allocation
mmoire et assignation.
Exemple de suitPile[] :
Dclaration : static public SuitPile suitPile[] ;
Allocation : suitPile = new SuitPile[4] ; on rserve de la mmoire
pour les rfrences suitPile[0], . . . , suitPile[3] (c..d. n octets pour
les 4 pointeurs, en interne). Noter que le constructeur SuitPile() nest
pas encore appel.
Assignation :
84
IV.1
1.1 Paquetages
85
86
But
addKeyListener(KeyListener)
repaint(Graphics)
paint(Graphics)
But
setLayout(LayoutManager)
add(Component), remove(Component)
Une Window (fentre) est une surface 2 dimensions sur laquelle on peut
dessiner et qui peut tre affiche. Parmi les mthodes de Window :
87
methode()
But
show()
toFront()
toBack()
But
setResizable()
setTile(String), getTitle()
setCursor(int)
setMenuBar(MenuBar)
But
setTitle(String)
setSize(int, int)
show()
paint()
Hrite
Hrite
Hrite
Hrite
de
de
de
de
Frame.
Component.
Window.
Component, redfini.
La puissance dAWT, comme celle de tout cadre logiciel, vient de lutilisation de variables polymorphes.
Lorsque la mthode show() de la classe Window est appele :
elle appelle setVisible() de la classe Component ;
cette dernire appelle repaint(),
qui appelle paint().
Le code de lalgorithme utilis par setVisible() et repaint() rside dans
la classe Component. Lorsquelle est excute, le cadre (AWT) pense quil
ne sagit que dun instance de Component.
En ralit, la mthode paint() qui est finalement excute est celle redfinie
dans la classe PinBallGame.
88
Fentre gnrale
Une classe hrite de JFrame contiendra le main() de lapplication
Contient une fille unique, de type JRootPane
Cette fille contient 2 filles :
layeredPane de type JLayeredPane, responsable des composants pouvant
tre empils les uns au dessus des autres
glassPane de type JPanel, responsable de la capture des vnements
souris
layeredPane a 2 filles :
MenuBar de type JMenuBar, responsable des composants menus
contentPane de type JPanel, responsable des autres composants
sous-classe de Frame de AWT
Fonctionne de la mme faon part quelle contient un un contentPane de
type JPanel
Tout composant (ou sous-Panel) c doit tre ajout la contentPane par
getContentPane().add(c)
89
1.7 Conteneurs
classe abstraite Container (sous-classe de Component), avec sous-classes :
Panel : conteneur de base, pour grouper des composants Admet un analogue
Swing JPanel hritant de JComponent
ScrollPane : conteneur avec barres de dfilement, mais pour un seul composant Admet un analogue Swing JScrollPane hritant de JComponent
Window : fentre (sans bordure, ni titre), pour cration fentres personelles
par drivation Admet un analogue Swing JWindow hritant de Window
Frame : Fentre "usuelle" avec bandeau en haut Admet un analogue Swing
JFrame hritant de Frame
Dialog : fentre secondaire, associe une fentre matresse (notamment
pour pop-up de dialogue) Admet un analogue Swing JDialog hritant de
Dialog
90
IV.2
91
Description
WindowEvent
ComponentEvent
FocusEvent
Source
92
ComponentEvent,
FocusEvent,
KeyEvent, MouseEvent
MenuItem
WindowEvent, Button
ActionEvent
List
ActionEvent, ItemEvent
ItemEvent
TextField
ActionEvent, TextEvent
TextEvent
ContainerEvent
Interface
Mthodes associes
KeyEvent
KeyListener
MouseEvent
MouseListener
MouseEvent
MouseMotionListener
ComponentEvent
ComponentListener
FocusEvent
WindowEvent
FocusListener
WindowListener
keyPressed(),
keyReleased(), keyTyped()
mouseClicked(),
mouseEntered(),
mouseExited(),
mousePressed(),
mouseReleased()
mouseDragged(),
mouseMoved()
componentHidden(),
componentMoved(),
componentResized(),
componentShown()
focusGained(), focusLost()
windowActivated(),
windowClosed(),
windowClosing(),
windowDeactivated(),
windowDeiconified(),
windowIconified(),
windowOpened()
IV.3
ActionListener
ItemListener
TextListener
AdjustmentListener
ContainerListener
93
actionPerformed()
itemStateChanged()
textValueChanged()
adjustmentValueChanged()
componentAdded(),
componentRemoved()
Gestionnaire de disposition
94
95
IV.4
4.1 tiquette
Tous les composants dinterface utilisateur, sauf les menus, sont des sous
classes de Component.
Une tiquette ou Label contient du texte qui est affich.
Exemple :
Label lab = new Label("score : 0 a 0");
add("South", lab);
4.2 Bouton
Un bouton est un composant souvent reprsent par une forme ronde et
rpondant aux interactions de lutilisateur.
On obtient une intercaction avec un bouton en attachant un objet ActionListener
(couteur actions) au bouton.
Lobjet ActionListener est averti lorsque le bouton est enfonc.
Button b = new Button("Fais le");
b.addActionListener(new doIt());
private class doIt implements ActionListener {
public void actionPerformed(ActionEvent e) {
96
97
4.3 Canevas
Un canevas ou Canvas est un composant ayant seulement une taille et la
possibilit dtre une cible pour des oprations de dessin.
Le canevas est souvent tendu (via jcextends) pour obtenir dautres types
de composants. Un exemple est la classe ScrollPane.
4.4 Ascenseur
Un ascenseur ou ScrollBar (en gnral un carr que lon peut faire glisser)
est utilis pour spcifier des valeurs entires dans un intervalle.
Il est affich dans une direction horizontale ou verticale.
On peut spcifier :
les bornes de lintervalle ;
lincrment de ligne (la distance dont lascenseur se dplace lorsque lon
clique sur lune de ses extrmits, souvent des petits triangles) ;
lincrment de page (la distance dont lascenseur se dplace lorsque lon
clique sur une partie darrire plan entre le carr glissant et lune de ses
extrmits).
Comme un bouton, une interaction avec lutilisateur est fournie en dfinissant un couteur qui est averti lorsque lascenseur est modifi.
Exemple dune classe ColorBar qui reprsente un ascenseur pour rgler
lintensit dune couleur. Le constructeur de la classe cr un ascenseur
vertical avec une valeur initiale de 40 et un intervalle gal [0,255].
private class ColorBar extends ScrollBar implements AdjustmentListener
{
public ColorBar(Color c)
{
super(ScrollBar.VERTICAL, 40, 0, 0, 255);
setBackground(c);
addAdjustmentListener(this);
}
public void adjustmentValueChanged(AdjustmentEvent e)
{
setFromBar(); // prendre la valeur de lascenseur en
98
utilisant getValue()
}
}
La couleur de fond est fournie en argument. Enfin lobjet est lui-mme un couteur
vnements dascenseur. Lorsque lascenseur est modifi, la mthode adjustmentValueChanged()
est excute.
Pour les 3 couleurs primaires, on prendra 3 ascenseurs et leur valeur sera obtenue
via la mthode setFromBar().
99
100
101
p.add(cb);
}
return(p);
}
}
Un groupe de checkbox ne devrait tre utilis que lorsque le nombre dalternatives est petit.
Un choix ou une liste devrait tre utilis si le nombre dalternatives dpasse
5.
Pour crer un Choice ou une List, le programmeur spcifie chaque alternative en utilisant addItem().
Un ItemListener peut tre attach lobjet. Lorsquune slection est faite,
lcouteur en est inform via la mthode itemStateChanged(). Le texte de
lentre slectionne peut tre obtenu via getSelectedItem().
Pour structurer un groupe de checkbox, le programmeur cr dabord un
CheckboxGroup. Cette rfrence est ensuite passe comme argument chacune des checkbox cre avec un e argument indiquant si le checkbox doit
tre initialement actif. Le dernier checkbox slectionn peut tre obtenu en
utilisant getSelectedCheckbox().
Puisquun groupe de checkbox est construit avec plusieurs composants, il
est presque toujours dispos sur un panneau (ou Panel). Dans lexemple,
une grille 52 est utilise comme disposition pour les 10 checkbox.
4.8 Panneau
Un panneau Panel est un Container qui agit comme un Component. Il
repsente une rgion rectangulaire qui possde son proper gestionnaire de
disposition (qui peut tre diffrent de celui de lapplication).
Des composants peuvent tre insrs dans un panneau. Le panneau est alors
lui-mme insr comme une seule unit dans la fentre de lapplication.
Utilisation dun panneau dans lexemple prcdent. La mthode makeChekcboxes()
cre un panneau pour contenir 10 checkbox. Il est structur en utilisant un
GridLayout 52. Puis ce groupe de 10 lments est trait comme un unique
lment et est plac gauche de la fentre de lapplication.
102
IV.5 Un exemple
IV.5
103
Un exemple
public ColorTest()
{
setTitle("Test de couleurs");
setSize(400, 600);
add("North", colorDescription);
add("East", makeColorButtons);
104
IV.5 Un exemple
{
private int index;
public BrightenButton(int i)
{
super(i == 0 ? "eclaire" : "assombrir");
index = i;
addEctionListener(this);
}
public void ActionPerformed(ActionEvent e)
{
if(index == 0)
setFromColor(current.brighter());
else
setFromColor(current.brighter());
}
}
105
106
IV.6
Botes de dialogue
But
setSize(int, int)
show()
setVisible(false)
setTitle(String), getTitle()
107
108
IV.7
Menus
Les divers menus sont nomms et ajouts la barre de menus via add() :
Menu helpMenu = new Menu("Aide");
bar.add(helpMenu);
IV.7 Menus
109
110
V Classe Url
Rfrences bibliographiques
Java et Internet Concepts et programmation, G. Roussel, E. Duris, N.
Bedon et R. Forax [RDBF02],
Java Network Programming, E.R. Harold [Har97].
V.1
Classe URL
1.1 Gnralits
Un URL (Uniform Resource Locator ou localisateur de ressource uniforme) est un schma de nommage et daccs des objets sur le rseau.
L objet est de fournir une interface simple afin dextraire des objets du
rseau. Un URL consiste en 6 champs : le protocole, le nom de dhte (ou
de machine), le numro de port, le chemin, le nom de fichier et la section.
Exemple : http ://sunsite.unc.edu :8080/pub/sound/monkey.au. On a ici :
le protocole : http
le nom dhte : sunsite.unc.edu
le numro de port : 8080
le chemin de fichier : /pub/sound/
le nom de fichier : monkey.au.
Syntaxe gnrale :
protocole ://nom-machine :no-port/chemin/nom-fichier#section
La classe URL permet dobtenir des fichiers HTTP, des fichiers URLs et
certains types multimdias.
Il y a en fait six classes et interfaces :
La classe URL, pour rapatrier des URLs du rseau.
La classe URLConnection
111
112
1.2 Constructeurs
La classe URL reprsente un URL, comme utilis sur le Web.
URL(String url) throws MalformedURLException
Cr un objet de type URL partir dune spcification textuelle, typiquement
de la forme http ://www.nas.gov/index.html
URL(String protocol, String host, String file) throws MalformedURLException
Ce constructeur suppose un numro de port par dfaut de lURL. Ce numro
dpend du protocole et doit tre gr par un gestionnaire de protocole.
URL(String protocol, String host, int port, String file) throws MalformedURLException
Ce constructeur cre un URL de toutes pices. Le protocole est typiquement
http ou ftp.
URL(String protocol, String host, int port, String file, URLStreamHandler
handler) throws MalformedURLException
Ce constructeur cre un URL de toutes pices avec un gestionnaire spcifique de flux dURL, de type URLStreamHandler. Cest le mcanisme recommand pour que des applets du JDK 1.2 utilisent des gestionnaires de
protocole spcifiques.
URL(URL context, String relative)
Cre un URL partir dun URL existant context et dun URL textuel relatif relative. Par exemple, si context est http ://serveur/ et relative est
document.html, lURL cre correspondra http ://serveur/document.html.
Si relative est un URL absolu (commenant par le champ de protocole,
par ex. http :), le rsultat est juste un URL correspondant relative.
Les applets se serviront souvent de ce constructeur, utilisant le rsultat de
getCodeBase() comme contexte.
URL(URL context, String relative, URLStreamHandler handler) throws MalformedURLException
Cre un URL partir dun URL existant context et dun URL textuel
relatif relative avec un gestionnaire spcifique de flux dURL, de type
URLStreamHandler. Par dfaut, le nouvel URL hrite dun URLStreamHandler
de context. Cest le mcanisme recommand pour que des applets du JDK
1.2 utilisent des gestionnaires de protocole spcifiques.
113
String getHost()
Renvoie le champ nom dhte de lURL.
int getPort()
Renvoie le champ numro de port de lURL.
String getFile()
Renvoie les champ chemin et nom de fichier de lURL.
String getRef()
Renvoie le partie rfrence (ou section) de lURL, si elle est prsente (partie
suivant le signe #).
boolean sameFile(URL other)
Renvoie true si lURL est gale other en ignorant le champ rfrence
(ou section) si elle est prsente.
String toExternalForm()
Renvoie une reprsentation sous forme de String de lURL, par ex. http ://x.y.z :80/fi
URLConnection openConnection() throws IOException
ouvre un socket pour lURL spcifi et renvoie un objet de type OpenConnection.
Ce dernier reprsente une connexion ouverte une ressource rseau. Cette
mthode est utilise lorsque lon veut communiquer directement avec le serveur. Lobjet de type URLConnection donne accs tout ce qui est envoy par
le serveur ; en plus du document lui-mme, sous forme brute (HTML, texte
ou binaire), lon voit tous les en-ttes requis par le protocole en cours dutilisation. Par exemple, si lon rapatrie un document HTML, GetConnection()
donnera accs au en-ttes HTTP suivi du flux HTML brut.
InputStream openStream() throws IOException
Cette mthode ouvre une connexion pour lURL correspondant et renvoie
un objet de type InputStream afin de lire son contenu. Les donnes obtenues sont de type brut (donnes ASCII pour un fichier texte, code HTML
pour un fichier HTML, etc.) et ne contiennent pas les en-tte de protocoles ;
pour les obtenir, se servir de openConnection(). Dans le cas du protocole HTTP, un appel openStream() envoie automatiquement une requte
HTTP et traite les en-tte associs. Cet appel est quivalent un premier
appel openConnection() suivi dun appel getInputStream() de la classe
URLConnection.
Object getContent() throws IOException
Cette mthode rcupre le contenu de lURL et renvoie une rfrence un
type Object. Le type rel de lobjet dpend du contenu de lURL. Si lURL
est une image et quun gestionnaire appripropri est disponible, un objet
de type ImageProducer est effectivement renvoy ; si le fichier est textuel
et quun gestionnaire est disponible, une objet de type String est renvoy.
Cet appel est un raccourci de lappel openConnection().getContent().
protected void set(String protocol, String host, int port, String file,
114
Permet une sous-classe dURL de changer les valeurs des diffrents champs :
protocole, nom dhte, chemin et nom de fichier, rfrence.
static void setURLStreamHandlerFactory(URLStreamHandlerFactory factory)
Cette mthode fixe le URLStreamHandlerFactory global pour lapplication
courante. Cette mthode est utilise lorsque lon cherche dvelopper un
gestionnaire de protocole spcifique. Le gestionnaire factory doit tre capable de renvoyer un gestionnaire appropri pour les types de protocoles
URL envisags. Cette mthode ne peut tre appele quune fois. Ceci dit,
lenvironnement Java inclut des gestionnaires de protocoles par dfaut,
contenant au moins HTTP. Laccs cette mthode est restreint par le
gestionnaire de scurit en vigueur. Des applets non autorises ne peuvent
appeler cette mthode. Pour cette raison, lextension (au sens de lhritage)
de la hirarchie de URL nest utile que pour des applications. Les applets
doivent spcifier un gestionnaire, de type URLStreamHandler, pour chaque
URL quelles construisent.
Une Exception : MalformedURLException
Indique un URL ayant des champs incorrects. Sous-classe de IOException.
Exemple de chargement dune page HTML :
URL url = new URL("http://java.sun.com/index.html");
InputStream in = url.openStream();
Reader reader = new InputStreamReader(in, "latin1");
BufferedReader bufferedReader = new BufferedReader(reader);
PrintWriter console = new PrintWriter(System.out);
String line;
while ((line = bufferedReader.readLine()) != null)
console.println(line);
console.flush();
bufferedReader.close();
VI.1
116
VI.2
Sockets : Clients
117
import java.net.*;
import java.io.*;
public class InetExample {
public static void main (String args[]) {
printLocalAddress ();
Reader kbd = new FileReader (FileDescriptor.in);
BufferedReader bufferedKbd = new BufferedReader (kbd);
try {
String name;
do {
System.out.print ("Enter a hostname or IP address: ");
System.out.flush ();
name = bufferedKbd.readLine ();
if (name != null)
printRemoteAddress (name);
} while (name != null);
System.out.println ("exit");
} catch (IOException ex) {
System.out.println ("Input error:");
ex.printStackTrace ();
}
}
static void printLocalAddress () {
try {
InetAddress myself = InetAddress.getLocalHost ();
System.out.println ("My name : " + myself.getHostName ());
System.out.println ("My IP : " + myself.getHostAddress ());
} catch (UnknownHostException ex) {
System.out.println ("Failed to find myself:");
ex.printStackTrace ();
}
}
118
119
Mthodes
Pour communiquer dun client au travers dune connexion TCP, il faut
crer une Socket, puis utiliser getInputStream() et getOutputStream()
pour communiquer avec le serveur distant.
InputStream getInputStream() throws IOException Cette mthode renvoie un InputStream, qui permet une communication par flux le long de la
connexion TCP. Pour des raisons defficacit, il est louable de bufferiser
les flux de Sockets.
InputStream getOutputStream() throws IOException Cette mthode renvoie un InputStream, qui permet une communication par flux le long de
la connexion TCP. Pour des raisons defficacit, il est louable de bufferiser les flux de Sockets. Dans le cas contraire, des transmissions dun
seul octet seront frquentes . . .
void close() thows IOException Cette mthode ferme lobjet Socket,
librant toute ressource systme et rseau utilise. Toute donne envoye
avant cet appel arrivera destination, sauf en cas de panne ou congestion rseau. Si l OutputStream de la Socket a t bufferis, lobjet
BufferedOutputStream devrait tre pralablement ferm, sous peine de
perdre les donnes contenues dans le tampon. Fermer lobjet Socket, celui InputStream ou celui OutputStream fermera la connexion rseau. Pas
de possibilit de fermeture partielle de connexion.
InetAddress getInetAddress() Renvoie ladresse IP de lhte distant.
int getPort() Renvoie le numro de port de lhte distant laquelle
lobjet Socket est connect.
InetAddress getLocalAddress() Renvoie ladresse locale ` laquelle lobjet Socket est attach ; cest linterface IP locale travers laquelle les
paquets sont envoys.
int getLocalPort() Renvoie le numro de port local auquel lobjet Socket
est attach. Cette valeur est assigne alatoirement si elle nest pas fournie
au constructeur.
void setSocketTimeout(int timeout) throws SocketException Fixe un
temps dexpiration, en milisecondes, au del duquel une lecture bloquante
sur cet objet Socket sera automatiquement arrte. Une valeur gale 0
rend nouveau les lectures bloquantes. Dans le cas darrt dune lecture,
une exception InterruptedIOException est leve.
int getSocketTimeout(int timeout) throws SocketException Renvoie
le temps dexpiration dune lecture. Une valeur gale 0 indique que les
lectures sont bloquantes.
void setTcpNoDelay(boolean on) throws SocketException Permet de
dactiver lutilisation de lalgorithme de Nagle sur une connexion socket.
Cet algorithme est utilis afin de rendre TCP plus efficace en retardant
120
lcriture de petites quantits de donnes jusqu ce que soit suffisamment de donnes aient t bufferises pour quun gros paquet puisse
tre envoy, soit toutes les donnes prtes tre envoyes au serveur sont
des accuss de rception. Pour des applications normales, lalgorithme
de Nagle accrot significativement les parformances, sauf pour certaines
applications bien particulires.
boolean getTcpNoDelay() throws SocketException Teste si lalgorithme
de Nagle est dsactiv. Renvoie false par dfaut.
void setSocketLinger(boolean on, int val) throws SocketException Permet un client de fixer un temps dexpiration maximum dune socket
TCP. Le protocole TCP garantit un acheminement sr des donnes transmises une socket. Ceci implique que lorsquune socket est ferme, la
connexion rseau ne se termine pas immdiatement ; elle reste ouverte le
temps que toutes les donnes soient achemines avec accus de rception.
Fixer un temps dexpiration signifie que le systme dexploitation nattendra que la priode spcifie aprs la fermeture dune socket avant de
fermer la connexion rseau. Si des donnes nont pas t transmises avec
succs durant cette priode, la connexion rseau est interrompue.
Lorsquune connexion rseau est ferme naturellement, il y a habituellement une priode de 4 minutes pendant laquelle une connexion identiqu ne peut tre recre (du mme port client au mme port serveur).
Ceci sert se protger contre les duplications involontaires de paquets ;
certains paquets peuvent tre retards dans certaines parties du rseau
et retransmis par la source. Mettre une temporisation supprimera cette
protection. Si une ancienne connexion est interrompue et une nouvelle
connexion identique est tablie avant que le retard de paquet soit coul,
le paquet en retard peut arriver et sinsrer dans la conversation. Cest
pourquoi, il est prfrable, en dehors de cas trs particuliers, dviter les
temps dexpiration de connexion.
int getSocketLinger() throws SocketException Renvoie le temps dexpiration d la connexion en cours ou 1 si loption est dsacive.
void setSendBufferSize(int size) throws SocketException Cette mthode demande au systme dexploitation de fixer le tampon denvoi (
SO_SNDBUF) size. Le systme dexploitation peut ignorer la requte . . .
int getSendBufferSize() throws SocketException Cette mthode renvoie la taille du tampon denvoi.
void setRecieveBufferSize(int size) throws SocketException Cette
mthode demande au systme dexploitation de fixer le tampon de rception ( SO_RCVBUF) size. Le systme dexploitation peut ignorer la
requte . . .
int getRecieveBufferSize() throws SocketException Cette mthode
121
122
//---------------
123
124
125
VI.3
Sockets serveurs
126
127
jusqu ce quun client se connecte sur le port sur lequel lobjet de type
ServerSocket est en coute. Un objet s de type Socket est renvoy,
correspondant une connexion TCP avec le client. Sil y a un gestionnaire de scurit, la mthode checkAccept() de ce dernier est appele
avec s.getInetAddress().getHostAddress() et s.getPort() comme arguments afin de sassurer que lopration est permise. Si elle ne lest pas,
une exception SecurityException est leve.
void close() throws IOException Cette mthode ferme le point de communication de type ServerSocket. Il ne ferme aucune des connexions dj
acceptes et non encore fermes, de sorte quun serveur peut fermer ce
point de communication et maintenir les connexions existantes avec ses
clients. Par contre, cet appel informe le systme dexploitation darrter
daccepter de nouvelles connexions de clients.
InetAddress getInetAddress() Renvoie ladresse locale laquelle le
point de communication de type ServerSocket est attach. Si aucune
adresse locale na t spcifie au constructeur, la valeur renvoye correspondra une adresse locale quelconque (typiquement 0.0.0.0).
int getLocalPort() Renvoie le numro de port sur lequel lobjet de
type ServerSocket est en coute. Ceci est utile si le numro 0 a t
fourni et donc un numro de port inutilis a t attribu par le systme
dexploitation.
void setSocketTimeout(int timeout) throws SocketException Cette mthode fixe une valeur de temps dexpiration, en milisecondes, aprs laquelle un appel accept() nayant pas reu de rponse sera interrompu
avec une exception de type InterruptedIOException. Une valeur de 0
inhibe le compteur dexpiration et un appel accept() bloque indfiniment.
int getSocketTimeout() throws IOException Renvoie la valeur du temps
dexpiration, ou 0 si aucune expiration nest valide.
protected final void implAccept(Socket s) throws IOException Les
sous-classes de ServerSocket utilisent cette mthode afin de redfinir
accept() et renvoyer leur propre sous classe de Socket. Par exemple un
objet de type MaServerSocket effectuera typiquement un appel du type :
MaSocket ms;
try {
implAccept(ms);
catch (IOException e) { ... }
128
VI.4
Serveurs itratifs
129
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 denvoi
in = new DataInputStream(client.getInputStream());
out = new PrintStream(client.getOutputStream());
//----------------------------// TRAITEMENT DU SERVICE DECHO
//----------------------------while (true) {
// lire une ligne
line = in.readLine();
if ((line == null) || (line.equals("exit")))
break;
// ecrire la ligne
out.println(line);
}
if (line == null) {
// Sortie du service : le client a termine
System.out.println ("Fermeture de socket client");
client.close ();
} else if (line.equals("exit")) { // Fermeture de socket serveur
System.out.println ("Fermeture des socket client & serveur");
client.close ();
server.close ();
break;
}
}// while(true)
}/* main() */
}/* class STServer */
130
VI.5
131
}
}// main()
// fermeture de socket
static void close (OutputStream out) {
if (out != null) {
try {
out.close ();
} catch (IOException ignored) { ; }
}
}// close()
132
VI.6
Serveurs concurrents
133
134
VII.1
1.1 RMI
Historiquement les rseaux se rencontrent dans 2 types dapplications :
le transfert de fichiers, au travers de FTP, SMTP (Simple Mail Transfer
Protocol), HTTP (HyperText Transport Protocol), . . .
xcution dun programme sur une machine distante, au travers de telnet,
rlogin, RPC, . . .
RMI (Remote Method Invocation) : mcanisme permettant un programme
Java dappeler certaines mthodes sur un serveur distant.
Peut tre vu comme un moyen de dfinir des protocoles sur mesure et des
serveurs avec un minimum defforts.
136
VII.2
Scurit Srialisation
2.1 Scurit
Les activits dun objet distant sont limites dune manire analogue la
limitation des activits dune applet.
Un objet SecurityManager vrifie quune opration est autorise par le
serveur.
Des gestionnaires de scurit spcifiques peuvent tre dfinis.
Une authentification par cl publique peut tre utilise pour vrifier lidentit dun utilisateur et autoriser diffrents utilisateurs diffrents niveaux
daccs un objet distant.
Par exemple, le grand public peut tre autoris consulter une base de
donnes, mais pas la modifier. Le personnel interne dune entreprise peut
tre autoris consulter et mettre jour la base.
2.2 Srialisation
Lorsquun objet est pass ou renvoy dune mthode Java, ce qui est rllement transfr est une rfrence lobjet.
Dans les implantations actuelles de Java, les rfrences sont des pointeurs
double indirection ; ils pointent sur les zones mmoire de stockage des objets
de la machine virtuelle.
Passer des objets dune machine virtuelle une autre pose quelques problmes.
2 solutions possibles :
137
on passe une rfrence distante (qui pointe sur des zones mmoires de la
machine distante),
on passe une copie de lobjet.
Lorsque la machine locale passe un objet distant la machine distante, elle
passe en fait une rfrence distante. Lobjet na en ralit pas quitt la
machine distante.
Lorsque la machine locale passe lun de ses propres objets la machine
distante, elle ralise une copie de lobjet quelle envoie.
Pour copier un objet, il faut un moyen de convertir cet objet en un flux
doctets.
La srialisation est un schma qui convertit les objets en un flux doctets qui
peut tre envoy dautres machines. Ces dernires reconstruisent lobjet
original partir des octets.
Ces octets peuvent galement tre crits sur disque et lus ultrieurement ;
on peut donc sauvegarder ltat dun objet individuel.
Pour des raisons de scurit, seulement certains objets peuvent tre
srialiss.
Tous les types primitifs ainsi que les objets distants peuvent tre srialiss, mais les objets locaux ne peuvent ltre que sils implantent linterface
Serializable.
Liste des classes srialisables :
Srialisable
java.lang.Character
java.lang.Boolean
java.lang.String
java.lang.Throwable
java.lang.Number
java.lang.StringBuffer
java.util.Hashtable
java.util.Random
java.util.Vector
java.util.Date
java.util.BitSet
java.io.File
java.net.InetAdress
java.net.URL
java.awt.BorderLayout
java.awt.Color
java.awt.Dimension
java.awt.Event
java.awt.Font
Non srialisable
Thread
InputStream et classes filles
OutputStream et classes filles
JDBC ResultSet
...
138
VII.3
139
Des mthodes dobjets distants sexcutent sur le serveur mais peuvent tre
appeles par des objets au sein du client. Des mthodes dobjets non distants et srialisables sexcutent sur le client.
3.2 Communications
Les communications se ralisent par une srie de couches comme suit
Programme serveur
Programme client
Squelette
Souche
= Internet =
En fait le programme client converse avec une souche (stubs) et le programme serveur converse avec un squelette (skeleton).
Un client trouve un serveur appropri en utilisant un registre, qui possde
une mthode lookup().
Lorsquon appelle lookup(), cette dernire trouve la souche ncessaire pour
lobjet dsir, et le charge. Ce squelette peut provenir de nimporte quelle
plate-forme.
Un client appelle une mthode distante en utilisant une souche.
Lsouche (stub) est un objet spcial qui implante les interfaces distantes de
lobjet distant.
la souche possde des mthodes ayant les mmes signatures que
toutes les mthodes que lobjet distant exporte.
De fait, le client pense quil appelle une mthode de lobjet distant, mais en
ralit il appelle une mthode quivalente de la souche.
Les souches sont utiliss dans la machine virtuelle du client la place des
objets rels et de leurs mthodes qui rsident au sein du serveur. Lorsque
la souche est appele, elle passe lappel la couche de rfrence distante
(Remote Reference Layer).
La couche de rfrence distante contient un protocole de rfrence distante
indpendant des souche client et squelette serveur. Cette couche de rfrence distante est responsable de linterprtation des rfrences distantes.
Plus prcisment, les rfrences locales de la souche client sont converties en
rfrences distantes lobjet sur le serveur. Puis, les donnes sont passes
la couche transport.
140
3.3 Registres
Dans un mcanisme dappel de procdures distantes (RPC) tel quon le
trouve sous Unix, il y a un gestionnaire de numros de ports (port mapper)
qui maintient une table de paires (nom de service distant, numro de port).
Un processus client voulant effectuer un appel de procdure distant sadresse
au gestionnaire de ports, qui lui renvoie le numro de port correspondant au
service ( la procdure distante) demand. Le processus client peut alors
sy connecter et la procdure distante seffectue.
Le client na besoin de conntre que le numro de port du gestionnaire de
ports et le nom du service (de la procdure distante).
Le mcanisme de RMI, de manire similaire aux RPC, utilise un service
analogue au gestionnaire de port, nomm un (gestionnaire de) registre (registry).
Un registre est gnralement lanc sur la mme machine que le serveur.
un gestionnaire de regsitre correspond une unique paire numro
de de machine, numro de port et rciproquement.
Chaque gestionnaire de registre implante linterface Registry et fournit
donc des services :
denregistrement dobjet (dont des mthodes seront disponibles de manire distante),
dobtention de rfremce distante un objet,
de listage des objets enregistrs,
dannulation denregistrement dun objet.
VII.4
Implantation
VII.4 Implantation
141
Aprs avoir dfini une interface distante, il faut dfinir une classe qui
implante cette interface et tend java.rmi.UnicastRemoteObject.
La classe UnicastRemoteObject fournit un certain nombre de mthodes qui
se chargent des dtails de la communication distante.
En particulier, il y a le dcoupage et le rassemblement.
Dcoupage (marshaling) : conservion des arguemnts et des valeurs de retour
en un flux doctets qui peuvent tre envoys travers le rseau.
Exemple de BashoServeur, une classe qui implante linterface distante DoueDeParole
et qui tend UnicastRemoteObject
import java.rmi.*;
import java.rmi.server.*;
import java.net.*;
public class BashoServeur extends UnicastRemoteObject
implements DoueDeParole {
public BashoServeur() throws RemoteException {
super();
142
VII.4 Implantation
143
DoueDeParole.class
DoueDeParole.java
Le champ de protocole est ici rmi, qui signifie que lURL rfrence un objet
distant.
Le champ fichier (ici MatsuoBasho) spcifie le nom de lobjet distant.
Les champs de nom de machine et de numro de port optionnel sont inchangs par rapport au cas dHTTP.
144
VII.5
Paquetage java.rmi
145
But
Renvoie une souche (stub) associ lobjet distant rfrenc par lURL url. Cette
souche agit pour le client comme lobjet distant.
RemoteException est leve si lookup()
narrive pas trouver le registre spcifi
(souvent la suite dun connection time
out).
NotBoundException est leve si le nom spcifi dans url nest pas rpertori dans le
registre utilis.
AccessException est leve si le client nest
pas autoris se connecter ce registre.
UnknownHostException est leve si la machine rfrence dans url ne peut tre localise.
Un serveur utilise bind() pour associer un
nom comme MatsuoBasho un objet distant.
Si url est dja associe un objet local,
bind() lve une AlreadyBoundException.
Enlve lobjet scifi par url du registre
(effectue loppos de bind()).
146
But
Souche locale
Non
Souche
tante
Non
Non
Non
Non
Non
Non
Non
Non
Non
Non
Non
Non
Non
Non
Non
Non
Non
Non
Non
Non
Non
Non
Non
dis-
checkAccept(String host,
int port)
checkConnect(String
host, int port)
checkConnect(String
host, int port, Object
context)
checkConnect(String
fromHost, String toHost)
checkTopLevelWindow(Object
Window)
checkPackageAccess(String
pkg)
147
checkPackageDefinition(String
Une souche peut-elle crer des
pkg)
classes au sein du paquetage
pkg ?
checkSetFactory()
Non
Non
Non
Non
Non
Non
Non
Non
Oui,
si
la
machine
est
lune partir
desquelles
la souche a
t charge ;
sinon, non.
Non
Non
Non
Non
Non
Non (pourra
tre ajustable
par lutilisateur dans le
futur)
Non (pourra
tre ajustable
par lutilisateur dans le
futur)
Non
Non (pourra
tre ajustable
par lutilisateur dans le
futur)
Non (pourra
tre ajustable
par lutilisateur dans le
futur)
Non
Il y a galement 17 exceptions qui sont dfinies dans java.rmi. Un programme rseau peut avoir beaoucoup de raisons de ne pas fonctionner correctement. Pour avoir des programmes relativement fiables, il est ncessaire de grer (par catch) les diverses exceptions susceptibles dtre leves
par les mthodes utilises.
En 1 ire approximation, on peut se contenter de ne grer que RemoteException,
dont les 16 autres drivent.
148
VII.6
Paquetage java.rmi.registry
But
VII.7
149
Renvoie une rfrence au gestionnaire de
regsitre situ sur la machine host et
associ au numro de port 1099. Si la
localisation de
host choue, une exception UnkwonHostException est leve.
Toute autre cause dchec gnre une
RemoteException.
Renvoie une rfrence au gestionnaire de
regsitre situ sur la machine host et
associ au numro de port port. Si
la localisation de host choue, une exception UnkwonHostException est leve.
Toute autre cause dchec gnre une
RemoteException.
Paquetage java.rmi.server
150
Bibliographie
[Boo94]
[Bud98]
[Gro02]
[Har97]
[Lea97]
D. Lea. Concurrent Programming in Java. Design Principles and Patterns. Addison-Wesley, Reading, MA, 1997. Un des meilleurs, sinon
le meilleur, livre de programmation concurrente en Java.
[OW97]
152
[Ven99]
[Wei98]
M. A. Weiss.
Using Java.