BoundConcurrent.java

package fr.umlv.ji.tcp.server;
import java.net.*;
import javax.net.*;
import java.io.*;
import java.util.logging.*;
import java.util.prefs.*;
/**
 * Classe pour un serveur concurrent utilisant un nombre fixé de
 * processus léger, chacun gérant lui-même l'acceptation de connexion
 * rendant le service au client correspondant, avant d'accepter une
 * nouvelle connexion, etc.
 */
public class BoundConcurrent extends Server {
  /** Nombre de processus légers. */
  protected int threadNb = -1;
  /** Constructeur du serveur. */
  public BoundConcurrent(Logger log, Preferences prefs) {
    super(log,prefs);
  }
  /** Méthode affectant le nombre maximum de processus légers. */
  public void setThreadNumber(int nb) {
    threadNb = nb;
  }
  /** Définition de la méthode launch(). */
  public void launch() {
    try {
      bind();
    } catch (IOException e) {
      logger.log(Level.SEVERE,"bind",e);
      return;
    }
    if (threadNb==-1) 
      threadNb = getPreferences().getInt("threadNB",10);
    ThreadGroup group = new ThreadGroup("Service");
    for (int i=0; i<threadNb; i++) {
      String name = "pl"+i;
      try {
    Thread t = new Thread(group,new RunnableService(),name);
    t.start();
      } catch (NullPointerException e) {
    logger.log(Level.SEVERE,"No service available",e);
    break;
      }
    }
    if (group.activeCount()!=0)
      logger.info("Number of threads: " +group.activeCount());
  }
  /**
   * Classe interne, représentant le code à exécuter pour accepter une
   * connection et rendre le service de ce serveur au client
   * correspondant.
   */
  class RunnableService implements Runnable {
    public void run() {
      Socket serviceSocket;
      // Ce processus léger agit comme un serveur itératif
      while (true) {
    // Il accepte une connexion pendante, de manière synchronisée
    // sur l'objet socket serveur
    synchronized (serverSocket) {
      try {
        serviceSocket = serverSocket.accept();
      } catch (IOException e) {
        // En cas de problème, on arrête le serveur
        logger.log(Level.SEVERE,"Accept",e);
        break;
      }
    }
    // Une fois une socket de service obtenue, on rend le service
    // au client correspondant
    try {
      logger.info(Thread.currentThread().getName() +
              " traite le service " +
              service.getClass().getName());
      service.serve(serviceSocket);
      // Et on ferme la socket de service
      serviceSocket.close();
    } catch (IOException e) {
      logger.log(Level.WARNING,e.toString());
    }
      }
    }
  }
}