/* echo / serveur avec pool de threads Master Informatique 2012 -- Université Aix-Marseille Bilel Derbel, Emmanuel Godard */ import java.net.*; import java.util.concurrent.*; import java.io.*; class EchoServeur { private final Executor executor; // objet permettant de confier plusieurs // tâches en parallèle à un pool de threads /* Constructeur : création du pool de threads de taille déterminée dynamiquement: nombre quelconque de connexions, libération de ressources automatiquement */ public EchoServeur() throws IOException { executor = Executors.newCachedThreadPool(); System.out.println("Création du pool dynamique"); } /* Constructeur : création du pool de threads de taille constante nb */ public EchoServeur(int nb) throws IOException { executor = Executors.newFixedThreadPool(nb); System.out.println("Création du pool de taille fixe ("+nb+")"); } /* Démarrage et délégation des connexions entrantes */ public void demarrer(int port) { ServerSocket ssocket; // socket d'écoute utilisée par le serveur try { System.out.println("Lancement du serveur sur le port "+port); ssocket = new ServerSocket(port); ssocket.setReuseAddress(true); /* rend le port réutilisable rapidement */ while (true) { /* attendre et gérer indéfiniment les connexions entrantes */ executor.execute(new Handler(ssocket.accept())); } } catch (IOException ex) { ((ExecutorService)executor).shutdown(); System.out.println("Arrêt anormal du serveur."); System.out.println("Des tâches peuvent être non terminées."); return; } } public static void main(String[] args) { int argc = args.length; EchoServeur serveur; /* Traitement des arguments */ /* pool dynamique */ if (argc == 1) { try{ serveur = new EchoServeur(); serveur.demarrer(Integer.parseInt(args[0])); } catch (Exception e) {e.printStackTrace();} } // pool de taille fixe else if (argc == 3 && (args[0]).equals("-t")) { try{ serveur = new EchoServeur(Integer.parseInt(args[1])); serveur.demarrer(Integer.parseInt(args[2])); } catch (Exception e) {e.printStackTrace();} } System.out.println("Usage: java EchoServeur [-t nb] port"); return; } } /* echo des messages reçus (le tout via la socket). NB classe Runnable : le code exécuté est défini dans la méthode run(). */ class Handler implements Runnable { Socket socket; PrintWriter out; BufferedReader in; InetAddress hote; int port; Handler(Socket socket) throws IOException{ this.socket = socket; out = new PrintWriter(socket.getOutputStream(), true); in = new BufferedReader(new InputStreamReader(socket.getInputStream())); hote = socket.getInetAddress(); port = socket.getPort(); } public void run() { String tampon; long compteur=0; long pid = Thread.currentThread().getId(); try{ /* envoi du message d'accueil */ out.println("Bonjour "+hote+"! (vous utilisez le port "+port+")"); do { /* Faire echo et logguer */ tampon = in.readLine(); if ( tampon != null ) { compteur++; /* log */ System.err.println("["+hote+":"+port+"]("+pid+"): "+compteur+":"+tampon); /* echo vers le client */ out.println("> "+tampon); } else { break; } } while ( true ); /* le correspondant a quitté */ in.close(); out.println("Au revoir..."); out.close(); socket.close(); System.err.println("["+hote+":"+port+"]("+pid+"): Terminé..."); } catch (Exception e) { e.printStackTrace(); } } }