0% ont trouvé ce document utile (0 vote)
25 vues33 pages

060 JavaNIO

Transféré par

tapsobajacob18
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
25 vues33 pages

060 JavaNIO

Transféré par

tapsobajacob18
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

Programmation Réseau

Java NIO
E/S non-bloquantes

[email protected]

UFR Informatique

2012-2013

mercredi 13 mars 13
Non Blocking IOs : le problème

Entrées/Sorties non-bloquantes
• On considère en premier chef que les opérations
d’entrées/sorties sont bloquantes :

• tenter une telle opération met le demandeur en


attente jusqu’à ce que l’opération puisse être
réalisée (ou se révèle impossible)

• la logique est assez facile à gérer

• le synchronisme est fort

2
mercredi 13 mars 13
Non Blocking IOs : le problème

Le relevé de compteur ou la livraison de colis


• vous savez que le préposé doit passer le 12

• le 12 au matin (précautionneux vous vous levez à 6:00),


puis...

• vous attendez

• jusqu’à ce qu’il vienne...

• s’il ne vient pas, votre journée est gâchée, votre vie est
fichue

• dans la vie on finit par abandonner


3
mercredi 13 mars 13
Non Blocking IOs : le problème

Le relevé de compteur ou la livraison de colis


• vous savez que le préposé doit passer le 12

• le 12 au matin (précautionneux vous vous levez à 6:00),


puis...

• vous attendez

• jusqu’à ce qu’il vienne...

• s’il ne vient pas, votre journée est gâchée, votre vie est
fichue

• dans la vie on finit par abandonner


3
mercredi 13 mars 13
Non Blocking IOs : le problème

Entrées/Sorties non-bloquantes
• Une entrée/sortie non-bloquante correspond à la
situation dans laquelle on souhaite ne pas attendre
si l’entrée/sortie ne peut être réalisée

• pour faire autre chose, quitte à revenir tenter plus


tard

4
mercredi 13 mars 13
Non Blocking IOs : le problème

Le boulanger ou le boucher
• vous voulez du pain ou du steack haché

• vous allez chez le boulanger ou le boucher, mais il n’y en a pas ou plus

• vous n’attendez pas car on ne peut vous dire quand le boulanger


ou le boucher se décidera à en refaire, et vous avez autre chose à

faire...

• alors vous partez faire cette autre chose

• et puis vous revenez plus tard...et recommencez

• cette fois votre opération n’est pas bloquante : vous n’êtes


simplement pas servi et on vous laisse repartir

5
mercredi 13 mars 13
Non Blocking IOs : le problème

Asynchronous vs Non-blocking
• Il faut normalement distinguer

• la requête

• la réalisation de la requête

• l’asynchronisme autorise à ne pas être bloqué


pendant la réalisation

• la non-réalisation non-bloquante qui autorise à ne


pas être bloqué en attente de la possible réalisation

6
mercredi 13 mars 13
Non Blocking IOs : le problème

Le remplissage de la baignoire
• vous ouvrez le robinet

• il y a de l’eau, vous laissez couler synbcloqu


hronant
e
• en regardant bêtement jusqu’à ce que ça finisse
(en sirotant un délicieux cocktail)
n asy
• vous laissez couler mais vous partezon- nchr
bloq one
uant
immédiatement faire le repassage en attendant

• il n’y a pas d’eau bloq


uant
• vous attendez qu’elle revienne
non
• vous passez à autre chose (en refermant)-bloq
uant
7
mercredi 13 mars 13
Non Blocking IOs : un problème informatique

• serveur à double entrée... ???

• virtual hosting par exemple

• selon l’adresse internet à travers laquelle vous


vous adressez à lui, le serveur répond
différemment

• ainsi vous pouvez avoir sur une même


machine, un seul serveur web qui rend des
choses générales depuis le réseau externe
(interface externe) et des choses privées
depuis l’intérieur (interface interne)
8
mercredi 13 mars 13
Non Blocking IOs : un problème informatique

• le problème est :

• comment attendre sur deux choses à la fois ?

• si je fais

attendre_sur_canal_1()
attendre_sur_canal_2()

• en mode bloquant, si rien n’arrive sur le canal 1,


rien de ce qui arrive sur le canal 2 n’est traité, il
risque même de se remplir...

• la stratégie symétrique a le défaut symétrique!


9
mercredi 13 mars 13
Non Blocking IOs : un problème informatique

10
mercredi 13 mars 13
Non Blocking IOs : un problème informatique

• la stratégie « moi les Threads, ça m’connaît »

• un Thread par canal + des entrées/sorties


bloquantes

• le multithreading résoud le problème à sa façon


en introduisant de l’asynchronisme (intrinsèque
à la concurrence)

• bien entendu, on déplace le problème puisqu’il


faut maintenant gérer la concurrence

• ce n’est pas forcément mieux…


11
mercredi 13 mars 13
Non Blocking IOs : un problème informatique

• la stratégie « moi on m’la fait pas! »

• rappelons qu’au moins pour la lecture avec

• int InputStream.available() renvoie le


nombre d’octets pouvant être lus

• boolean Reader.ready() indique s’il est


possible de lire quelque chose (au moins 1
caractère)

• pour l’écriture nada!

• bien mais un peu faible…


12
mercredi 13 mars 13
Non Blocking IOs

• la stratégie, pas besoin de remplacer le problème


par un autre, peut-être que mon environnement
m’offre quelque chose d’assez riche…

• les entrées/sorties de java.io.* et java.net.*


sont bloquantes

• le package java.nio a été créé pour satisfaire


les besoins d’entrées/sorties non-bloquantes
(entre autres)

• mais aussi pour garantir une certaine efficacité


aux opérations d’entrées/sorties
13
mercredi 13 mars 13
Non Blocking IOs

Les canaux (Channels)


• le premier concept important (ici) est celui de
Channel de java.nio.channels, sans entrer
dans les détails il en existe essentiellement trois
déclinaisons intéressantes (toujours pour ce cours) :

• Channel est une interface avec deux méthodes

• close()
• boolean isOpen()

14
mercredi 13 mars 13
Non Blocking IOs

• Il en existe essentiellement trois déclinaisons


intéressantes (toujours pour ce cours) :

• ServerSocketChannel
• DatagramChannel
• SocketChannel
• et dont on devine bien les rôles respectifs

15
mercredi 13 mars 13
Non Blocking IOs

• DatagramChannel et SocketChannel sont


(entre autres) des ByteChannel

• c’est-à-dire que peut les utiliser pour lire ou écrire

• i.e. ce sont des ReadableByteChannel et


WriteableByteChannel

• par conséquent ils sont très similaires à des Socket


ou des DatagramSocket

16
mercredi 13 mars 13
Non Blocking IOs

• ServerSocketChannel est lui similaire à


ServerSocket

• on ne peut pas y lire ou y écrire


• mais on peut faire accept()

17
mercredi 13 mars 13
Non Blocking IOs

• aucune de ces classes ne possède de constructeur


directement accessible, il faut passer par une
méthode usine :

DatagramChannel DatagramChannel.open();

ServerSocketChannel ServerSocketChannel.open();

SocketChannel SocketChannel.open();

• qui créent un objet correspondant

18
mercredi 13 mars 13
Non Blocking IOs

• les canaux correspondant sont créés mais pas


connectés, il faut donc, si nécessaire, récupérer la
Socket, la ServerSocket ou la DatagramSocket
sous-jacente :

DatagramSocket socket();
ServerSocket socket();
Socket socket();

• qui renvoient un objet du bon type

• et effectuer l’association à l’aide des fonctions


habituelles
19
mercredi 13 mars 13
Non Blocking IOs

• pour des raisons pratiques il existe dans chaque


types de Sockets correspondant une méthode
permettant de retrouver le Channel associé s’il
existe :

*Channel getChannel();

20
mercredi 13 mars 13
Non Blocking IOs
by the Courtesy of RATP

• il faut noter que l’on peut alors modifier le caractère


bloquant ou non de ces objets via la méthode
(héritée de SelectableChannel) via

SelectableChannel configureBlocking(boolean);

• on peut aussi tester ce caractère bloquant via

boolean isBlocking();

• la modification du caractère bloquant ou non ne


doit être faite que si le Channel n’est pas encore
dans un Selector (voir plus loin)

21
mercredi 13 mars 13
Non Blocking IOs

Les sélecteurs (Selectors)


• outre les Channels et leur mode bloquant ou non,
le second point important est qu’il est possible de
demander à tout moment si certaines opérations
d’un ensemble prédéterminé sont possibles

• cette opération s’appelle la sélection et s’effectue


via un sélecteur (Selector)

• la création d’un Selector s’effectue grâce à

Selector();

22
mercredi 13 mars 13
Non Blocking IOs

• un Selector permet donc de sélectionner un certain


nombre d’opérations réalisables parmi un ensemble
d’opérations souhaitées

• toute opération souhaitée sur un Channel doit être


préalablement enregistrée dans un sélecteur à l’aide
de la méthode héritée de SelectableChannel :

SelectionKey register(Selector,int);

• Attention, on ne peut enregistrer un sélecteur que s’il


est en mode non-bloquant!

23
mercredi 13 mars 13
Non Blocking IOs

SelectionKey register(Selector,int);

• où :
• le second argument est l’ensemble des opérations
que l’on souhaite « surveiller » sur le Channel
• le retour est la clé de sélection qui pourra être
utilisée lors d’une future opération de sélection
pour déterminer ce qu’il est possible de réaliser à
ce moment là

24
mercredi 13 mars 13
Non Blocking IOs

• les opérations souhaitées doivent être compatibles


avec le Channel choisi et sont toujours parmi les 4
suivantes (et qui peuvent être combinées par
addition) :

SelectionKey.OP_ACCCEPT,
SelectionKey.OP_READ,
SelectionKey.OP_WRITE,
SelectionKey.OP_CONNECT

• On remarquera que chaque type de Channel fournit


l’ensemble des opérations souhaitables possibles via

int validOps();
25
mercredi 13 mars 13
Non Blocking IOs

• une fois le sélecteur configuré, on peut soit :

• attendre (donc en mode bloquant) qu’une des


opérations soit réalisable par appel à

int select();

• tester (donc en mode non bloquant) si l’une des


opérations est réalisable par appel à

int selectNow();

• le retour indique le nombre de clés sur lesquelles des


opérations sont réalisables
26
mercredi 13 mars 13
Non Blocking IOs

• la liste des clés concernées peut être extraite par


appel à
Set<SelectionKey> selectedKeys();

• un itérateur peut ensuite être employé pour


parcourir cette liste afin de retrouver pour chaque
clé :
• les opérations possibles via
int readyOps();
• et le canal concerné via
SelectableChannel channel();

27
mercredi 13 mars 13
Non Blocking IOs

• Important : lors du parcours, il est essentiel de


penser à supprimer la clé de sélection via l’itérateur
si un traitement correspondant a été réalisé (ou va
l’être)

28
mercredi 13 mars 13
Non Blocking IOs

• dans l’exemple qui suit, on met en place de quoi


permettre à un serveur d’attendre des connexions
entrantes sur deux ports en même temps

29
mercredi 13 mars 13
Non Blocking IOs

public static ServerSocketChannel


createServerChannel(Selector s,int port) {
try {
// créé un canal serveur
ServerSocketChannel ssc = ServerSocketChannel.open();
// positionne-le en mode non-bloquant
ssc.configureBlocking(false);
// on configure la Socket sous-jacente
ServerSocket ss = ssc.socket();
ss.bind(new InetSocketAddress(port));
// on configure le sélecteur
ssc.register(s,ssc.validOps());
return ssc;
} catch(Exception e) {
e.printStackTrace(); System.exit(1);
}
return null;
}
30
mercredi 13 mars 13
Non Blocking IOs

public static void main(String []args) {


try {
// Get a selector
Selector s = Selector.open();
// Create the non-blocking channels, bind and register them
ServerSocketChannel ssc1 =
createServerChannel(s,50123);
ServerSocketChannel ssc2 =
createServerChannel(s,50124);

31
mercredi 13 mars 13
Non Blocking IOs

// Catch incoming connection requests


while (true) {
System.out.println("Waiting for incoming connections");
s.select();
Iterator<SelectionKey> it = s.selectedKeys().iterator();
while (it.hasNext()) {
// Get one key, and remove it from the set
SelectionKey sk = it.next(); it.remove();
// Get the channel
ServerSocketChannel ssc =
(ServerSocketChannel)sk.channel();
// accept
Socket sock = ssc.socket().accept();
// Launch a server with this service’s Socket
new Server(sock,ssc.socket().getLocalPort()).start();
}
}
} catch(Exception e) { e.printStackTrace(); System.exit(1); }
}

32
mercredi 13 mars 13

Vous aimerez peut-être aussi