2. Un Serveur Séquentiel

2.1. Principe

On va simplement ajouter une boule infinie autour du code précedent, que l’on organise un peu. La méthode main() se réduit à la création du serveur et à son exécution (les try catch la rende un brin verbeuse).

2.2. Méthode Main

Seules les lignes 10 et 19 font vraiment quelque chose, respectivement : la ligne 10 crée le serveur et la ligne 19 l’exécute.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
      public static void main(String[] args) {
              /* On crée puis lance le serveur */
              Serveur_Ameliore Mon_serveur = null;
              if (args.length != 1) {
                      System.err.println("usage: java "+ Serveur_Ameliore.class.getCanonicalName()
                                                      + " serverPort");
                      System.exit(-1);
              }
              try {
                      Mon_serveur = new Serveur_Ameliore(Integer.parseInt(args[0]));
              } catch (NumberFormatException e) {
                      System.out.println("Format du port incorrect \n:  format exception for "
                                                      + e.getMessage());
                      System.exit(-1);
              } catch (IOException e) {
                      System.out.println("Impossible de créer le  socket server : " + e);
                      System.exit(-1);
              }
              Mon_serveur.run();
      }

2.3. La Méthode run()

Dans cette méthode le serveur se contente de :

  1. D’attendre et d’accepter un client ligne 6).
  2. Puis de servir le client (ligne 16).
  3. De recommencer à l’infini (ligne 3)

Ce sont les vérifications et les message pour l’utilisateur qui rende le code long car au fond il se limite à 3 instructions.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
      public void run() {
              Socket ma_connection = null;
              while (true) {

                      try {                   //  Attente bloquante connexion
                              ma_connection = this.mon_connecteur.accept();
                      } catch (IOException e) {
                              System.out.println("Impossible de détacher une socket  : " + e);
                              System.exit(-1);
                      }
                      int c_port = ma_connection.getPort();
                      String c_ip = ma_connection.getInetAddress().toString();
                      System.out.format("Un client est arrivé avec IP : %s sur le port %d\n", c_ip,c_port);
                      /* On traite le client que l'on a associé */
                      try {
                              Service_Client(ma_connection);
                      } catch (IOException e) {
                              System.out.println("Erreur de Service Client  : " + e);
                              System.exit(-1);        }
              }
      }

2.4. La Méthode Service_Client()

Dans cette méthode le serveur reçoit les données envoyées par le client en les lisant ligne à ligne de façon bloquante.

Le code se résume à quelques opérations :

  1. En lignes 3-5 on récupère de flux entrant de données.
  2. En ligne 7 on récupère le flux de sortie.
  3. En lignes 12-13 on déclare un compteur de ligne et une chaine où stocker le message du client.
  4. En ligne 20 on envoie un message au client, l’opération n’est pas bloquante et on ne sait pas si le client la reçoit.
  5. Le while de la ligne 21 contient une instruction bloquante – cf le serveur jouet –
  6. Le If de la ligne 25 permet de tester si le client à demandé de terminer la transmission, si oui on clot la socket (ligne 30) et on termine en quittant la méthode de service (ligne 31).
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
  private Boolean Service_Client(Socket la_connection) throws IOException {
              /* On Associe une file d'entrée a la connection */
              InputStreamReader isr = new InputStreamReader(la_connection.getInputStream());
              /* On transforme cette file en file avec tampon */
              BufferedReader flux_entrant = new BufferedReader(isr);
              System.out.println("Tampon entree attache ");
              PrintWriter ma_sortie = new PrintWriter(la_connection.getOutputStream(), true);
              System.out.println("Sortie attachée");
              System.out.println("Prêt à servir le Client : "+ la_connection.getRemoteSocketAddress());

              String clientName = la_connection.getRemoteSocketAddress().toString();
              String message_lu = new String();
              int line_num = 0;

              /*
               * On lit le flux_entrant ligne à ligne ATTENTION : La fonction readline
               * est Bloquante readline retourne null si il y a souci avec la
               * connexion On s arrete aussisi connexion_non_terminee est vraie
               */
              ma_sortie.format("Bonjour %s j attends tes données  \n",clientName);
              while  (  (message_lu = flux_entrant.readLine()) != null))   {
                      System.out.format("%d: ->  [%s]\n", line_num, message_lu);
                      line_num++;
                      /* si on recoit Finish on clot et annonce cette terminaison */
                      if (message_lu.contains(Finish)) {
                              System.out.println("Reception de  " + Finish
                                              + " -> Transmission finie");
                              // On ferme la connection
                              System.out.format("Je clos la connection  %s :\n",clientName);
                              terminer(la_connection);
                              return (true);
                      }
              }
              return false;

2.5. Exemple de Code pour le Serveur Amélioré

Ici c’est juste le récapitulatif.

package td1;
/* On  importe les  classes  Reseau, Entrees Sorties, Utilitaires */
import java.net.*;
import java.io.*;


public class Serveur_Ameliore {
	ServerSocket mon_connecteur;  // serveur de socket du serveur amélioré
	/* Port d'écoute */
	private int port;
	final String Finish = "" + (char) 4;  //Signal de fin de connection aussi nommé EOT  ctrl-d

	public Serveur_Ameliore(int cport) throws IOException {
		port = cport;
		this.mon_connecteur = new ServerSocket(port); 		//Creation du gestionnaire de socket 
		System.out.format("Serveur Amélioré  lancé sur le  port %d\n", port);
	}
	private  void terminer(Socket ma_connection){
	    if (ma_connection != null)       	
	    {
		    try 	{
			ma_connection.close(); 
			System.out.format("Socket fermee \n"); 
		    }
		    catch ( IOException e )   { System.out.println("weird, nawak .... \n ");}     // do nothiing } 
		}}
		
	public void run() {
		Socket ma_connection = null;  		// file instanciée pour commmuniquer avec le client
		while (true) {
			// // /* Attente bloquante connexion */
			try {
				ma_connection = this.mon_connecteur.accept();
			} catch (IOException e) {
				System.out.println("Impossible de détacher une socket  : " + e);
				System.exit(-1);
			}
			int c_port = ma_connection.getPort();
			String c_ip = ma_connection.getInetAddress().toString();
			System.out.format("Un client est arrivé avec IP : %s sur le port %d\n", c_ip, c_port);
						/* On traite le client que l'on a associé */
			try {
				Service_Client(ma_connection);
			} catch (IOException e) {
				System.out.println("Erreur de Service Client  : " + e);
				System.exit(-1);	}
		}
	}
	private Boolean Service_Client(Socket la_connection) throws IOException {
		/* On Associe une file d'entrée a la connection */
		InputStreamReader isr = new InputStreamReader(la_connection.getInputStream());
		/* On transforme cette file en file avec tampon */
		BufferedReader flux_entrant = new BufferedReader(isr);
		System.out.println("Tampon entree attache ");
		// On récupère la file de sortie
		PrintWriter ma_sortie = new PrintWriter(la_connection.getOutputStream(), true);
		System.out.println("Sortie attachée");
		
		String clientName = la_connection.getRemoteSocketAddress().toString();
		System.out.format("Prêt à servir le Client %s\n", clientName);

		String message_lu = new String();
		int line_num = 0;
		/*
		 * On lit le flux_entrant ligne à ligne ATTENTION : La fonction readline
		 * est Bloquante readline retourne null si il y a souci avec la
		 * connexion On s arrete aussisi connexion_non_terminee est vraie
		 */
		ma_sortie.format("Bonjour %s j attends tes données  \n",clientName);
		while  ((message_lu = flux_entrant.readLine()) != null) {
			System.out.format("%d: ->  [%s]\n", line_num, message_lu);
			line_num++;
			/* si on recoit Finish on clot et annonce cette terminaison */
			if (message_lu.contains(Finish)) {
				System.out.println("Reception de  " + Finish
						+ " -> Transmission finie");
				// On ferme la connection
				System.out.format("Je clos la connection  %s :\n",clientName);
				terminer(la_connection);
				return (true);
			}
		}
		return false;

	}
	public static void main(String[] args) {
		/* On crée puis lance le serveur */
		Serveur_Ameliore Mon_serveur = null;
		if (args.length != 1) {
			System.err.println("usage: java "+ Serveur_Ameliore.class.getCanonicalName()
							+ " serverPort");
			System.exit(-1);
		}
		try {
			Mon_serveur = new Serveur_Ameliore(Integer.parseInt(args[0]));
		} catch (NumberFormatException e) {
			System.out.println("Format du port incorrect \n:  format exception for "
							+ e.getMessage());
			System.exit(-1);
		} catch (IOException e) {
			System.out.println("Impossible de créer le  socket server : " + e);
			System.exit(-1);
		}
		Mon_serveur.run();
	}

}