package net ;

import java.net.* ;
import java.io.* ;

/** Cette classe abstraite permet de creer un serveur TCP/IP
    generique dont il faudra implementer la methode gereClient
    pour le specialiser. */
    
abstract public class TCPServeur implements Cloneable, Runnable {
    
    Thread thread = null ;
    private volatile Thread blinker;
    
    private ServerSocket serveur = null ;   // != null si thread serveur
    private Socket client = null ;          // != null si thread client
    static int compteurClient = 0 ;
    protected int numeroClient = 0 ;
 

    
    private int port;
    /** Lance le serveur attaché à un port donné.
        @param port le port d'attachement.
        @exception IOException si le serveur n'a pas pu être créé. */
    
    public synchronized void startServeur( int port ) throws IOException{
        if( thread == null ){
        	if (port == 0) 
        		serveur = new ServerSocket() ;
        	else
        		serveur = new ServerSocket( port ) ;
            thread = new Thread( this ) ;
            thread.start() ;
            this.port = port;
        }
    }
    
    /** Stoppe le serveur.
        @exception IOException si le serveur n'a pas pu être créé. */
    
    public synchronized void stopServeur() throws IOException{
        if( serveur != null ){
            Thread.currentThread().interrupt();
            blinker = null;
            serveur.close() ;
        }
    }
    
    public void run(){
        if( serveur != null ){  // serveur
            Thread thisThread = Thread.currentThread();
            blinker = thisThread ;
            while( blinker == thisThread ){
                try{
                    Socket socketClient = serveur.accept() ;
                    TCPServeur nouvelleSocket = (TCPServeur)clone() ;
                    nouvelleSocket.serveur = null ;     // client
                    nouvelleSocket.client = socketClient ;
                    TCPServeur.compteurClient++ ;
                    nouvelleSocket.numeroClient = TCPServeur.compteurClient ;
                    System.out.println( nouvelleSocket.numeroClient ) ;
                    nouvelleSocket.thread = new Thread( nouvelleSocket ) ;
                    nouvelleSocket.thread.start() ;
                } catch( Exception e ){
                    System.out.println( e ) ;
                }
            }
        } else {                // traitement d'un client
        	gereClient(client) ;
        	try {
				client.close();
			} catch (IOException e) {
				// Exception = elle est déjà fermée : tout va bien
			}
			System.out.println("Fin d'un Thread de traitement de client couche TCP");
        }
    }
    

    public int getPort () {
    	return port;
    }
    


    
    /** Specialise le serveur pour un client donné. Implémentez cette méthode
        pour spécialiser le serveur.
        @param client la socket pour communiquer avec un client */    
    abstract public void gereClient( Socket client ) ;
}