19. Les serveurs TCP/IP - SocketServer

Nous allons voir comment réaliser une application serveur TCP/IP. La classe SocketServer permet de se mettre en attente d'un client sur un port. La méthode SocketServer.accept() retourne un objet de la classe Socket lorsqu'un client veut se connecter. C'est grâce à cet objet que l'on pourra établir une connexion avec le client.

Serveur d'heure

import java.net.*;
import java.io.*;
import java.util.Date;

class serveurHeure {

    public static void main(String args[]) {
        try {
            ServerSocket sks = new ServerSocket(11111);
            Socket sk = sks.accept();
            System.out.println(sk.toString());
            DataOutputStream out = new DataOutputStream(sk.getOutputStream());
            out.writeBytes("Bienvenue "+sk.getInetAddress().getHostName()+
                            ". Il est actuellement "+new Date()+"\n");
            sk.close();
            sks.close();
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
    }
    
}
Le résultat que l'on peut voir apparaitre sur la console oł l'on a lancé le serveur est :

Socket[addr=129.194.184.2,port=2569,localport=11111]
Pour se connecter à ce serveur, on peut utiliser telnet ou l'utilitaire jnetcat qui a été décrit dans les pages décrivant la classe Socket. Le client qui se connecte sur le port 11111 du serveur peut voir apparaitre un message du type :

Bienvenue eig. Il est actuellement Thu May 30 14:12:35 MET DST 1996

Généralement, on désire pouvoir servir plusieurs applications clientes à partir du même serveur, comme c'est le cas pour FTP et HTTP. Nous allons voir comment implémenter un serveur multi-thread, qui crée un processus par client. Nous déclarons une classe connexion qui est capable de traiter les entrées/sorties d'un client que nous instancions chaque fois qu'un client se connecte sur le port serveur.

Le programme ci-dessous est un exemple de serveur qui peut s'accomoder de plusieurs clients concurrement. Lorsqu'un client s'y connecte, le serveur initialise un compteur à 0, et chaque nombre que le client lui envoie est additionné à ce compteur.

Serveur multi-clients

/*
 * Serveur multi-clients
 * Additionne tous les nombres fournis par les clients
 */

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

public class serveurAdd {

    static int port;
    
    public static void main(String args[]) {
        if (args.length != 1)
            System.out.println("usage : serveurAdd port");
        else {
            ServerSocket serveur;
            try {
                port = Integer.parseInt(args[0]);
            } catch (NumberFormatException e) {
                System.out.println("le port doit etre une valeur entre 1024 et 65535");
                System.exit(1);
            }
            try {
                serveur = new ServerSocket(port);
                for (;;)
                    new connexion(serveur.accept());
            } catch (IOException e) {
                System.out.println("erreur a la creation d'un objet Socket : "+e.getMessage());
                System.exit(1);
            }
        }
    }

}

class connexion implements Runnable {

    Socket client;
    DataInputStream depuisClient;
    PrintStream versClient;
    int somme = 0;
    
    public connexion(Socket client) {
        this.client = client;

        try {
            // creation des flux de/vers le client
            depuisClient = new DataInputStream(client.getInputStream());
            versClient = new PrintStream(client.getOutputStream());

            // message d'accueil
            versClient.println("Bienvenue sur le serveur additionneur");
            versClient.println("Entrez un nombre suivi de entree");
        } catch (IOException e) {
            try { client.close(); } catch (IOException ee) {}
        }
        new Thread(this).start();
    }

    public void run() {
        try {
            String lue;
            while ((lue = depuisClient.readLine()) != null) {
                somme += Integer.parseInt(lue);
                versClient.println("merci. La somme est maintenant "+somme);
            }
            versClient.println("Au revoir !");
        } catch (IOException e) {
            System.out.println("Exception entree/sortie : "+e.getMessage());
        } catch (NumberFormatException e) {
            versClient.println("Seul les nombres sont autorises. Au revoir !");
        }
        stop();
    }
    
    public void stop() {
        try {
            client.close();
        } catch (IOException e) {
            System.out.println("exception a la fermeture d'une connexion : "+e);
        }
    }
    
}

Index général - Index concepts - Règles BNF
© 1996, DIP Genève, Alexandre Maret & Jacques Guyot
page générée Fri Jun 21 15:41:39 MET DST 1996