Adloun

Réseau : sockets client/serveur

Cours · programmation Java (école d'ingénieur), chapitre 16 · école d'ingénieur, informatique · le début du chapitre, la suite sur Adloun

Quand vous ouvrez une page web, votre navigateur (le client) envoie une demande à un programme qui tourne sur une machine distante (le serveur), qui lui renvoie la page. La messagerie, les jeux en ligne, les bases de données, les applications mobiles fonctionnent de la même façon : deux programmes, souvent sur deux machines, qui échangent des messages selon des règles convenues. Ce chapitre montre comment écrire en Java les deux côtés de cet échange, à l'aide des sockets.

À faire sur votre ordinateur

Les programmes de ce chapitre ouvrent des connexions réseau : ils ne tournent pas dans l'Éditeur Java du navigateur, mais avec un JDK installé sur votre ordinateur. Tous les exemples se contentent de la machine locale : on lance le serveur dans un terminal, le client dans un second terminal, et ils communiquent sans même passer par Internet.

Objectifs du chapitre

  • Connaître le modèle client/serveur et le vocabulaire du réseau : adresse IP, port, TCP, UDP, localhost.
  • Écrire un serveur TCP (ServerSocket) et un client (Socket) qui échangent des lignes de texte.
  • Définir un petit protocole et le programmer des deux côtés.
  • Servir plusieurs clients à la fois, un fil par client.
  • Traiter les erreurs propres au réseau : connexion refusée, port occupé, délai d'attente dépassé.
  • Savoir envoyer un datagramme UDP et télécharger une page web avec HttpClient.

16.1 Le modèle client/serveur

Définition 16.1Client, serveur

Un serveur est un programme qui attend des demandes et y répond ; il tourne en permanence et peut servir de nombreux clients. Un client est un programme qui prend l'initiative de contacter un serveur, lui envoie des requêtes et reçoit ses réponses.

16.1.1 Adresses et ports

Pour joindre un programme sur le réseau, il faut deux informations :

L'adresse 127.0.0.1, de nom localhost, désigne toujours la machine elle-même (la boucle locale) : un client et un serveur qui tournent sur le même ordinateur s'y retrouvent, sans réseau extérieur. La classe InetAddress représente une adresse :


import java.net.InetAddress;
import java.net.UnknownHostException;

/** Chapitre 16 — adresses IP et noms de machines. */
public class Adresses {
    public static void main(String[] args) throws UnknownHostException {
        InetAddress local = InetAddress.getByName("localhost");
        System.out.println("localhost     -> " + local.getHostAddress());
        System.out.println("boucle locale -> " + InetAddress.getLoopbackAddress());
        InetAddress ip = InetAddress.getByName("192.168.1.20");      // aucune résolution réseau
        System.out.println("adresse lue   -> " + ip.getHostAddress());
        try {
            InetAddress.getByName("machine-qui-n-existe-pas.invalid");
        } catch (UnknownHostException e) {
            System.out.println("nom inconnu   -> " + e.getClass().getSimpleName());
        }
    }
}

localhost     -> 127.0.0.1
boucle locale -> localhost/127.0.0.1
adresse lue   -> 192.168.1.20
nom inconnu   -> UnknownHostException

16.1.2 TCP et UDP

Deux protocoles de transport sont disponibles.

TCPUDP
connexion établie avant l'échangepas de connexion
flot d'octets continu, dans les deux sensmessages indépendants (datagrammes)
fiable : rien n'est perdu, l'ordre est conservéni garantie de livraison, ni d'ordre
plus lent à établirtrès léger, rapide
web, courrier, fichiers, bases de donnéesvisioconférence, jeux, mesures

La plupart des applications utilisent TCP ; c'est lui que nous étudierons d'abord.

Définition 16.2Socket

Une socket (« prise ») est l'extrémité d'une connexion réseau, du point de vue d'un programme. En TCP, une connexion relie deux sockets ; chacune offre un flux d'entrée (ce que l'autre côté envoie) et un flux de sortie (ce que l'on envoie), exactement comme un fichier ouvert (chapitre 14).

16.2 Un premier serveur : l'écho

Le paquetage java.net fournit deux classes :

De chaque côté, on obtient ensuite les flux avec getInputStream() et getOutputStream(), que l'on emboîte comme pour un fichier : un BufferedReader pour lire des lignes, un PrintWriter pour en écrire.

Notre premier serveur renvoie chaque ligne qu'il reçoit, précédée de « écho : ».


import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;

/** Chapitre 16 — un serveur d'écho : il renvoie chaque ligne qu'il reçoit. */
public class ServeurEcho {
    public static void main(String[] args) throws IOException {
        int port = 5000;
        try (ServerSocket serveur = new ServerSocket(port)) {
            System.out.println("Serveur à l'écoute sur le port " + port);
            while (true) {
                try (Socket client = serveur.accept();           // attend un client
                     BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream(), StandardCharsets.UTF_8));
                     PrintWriter out = new PrintWriter(new OutputStreamWriter(client.getOutputStream(), StandardCharsets.UTF_8), true)) {
                    System.out.println("Client connecté : " + client.getInetAddress().getHostAddress()
                            + ", port " + client.getPort());
                    String ligne;
                    while ((ligne = in.readLine()) != null) {     // null : le client a fermé
                        System.out.println("reçu : " + ligne);
                        out.println("écho : " + ligne);
                    }
                    System.out.println("Client déconnecté");
                }
            }
        }
    }
}

La suite du cours est sur Adloun

Le chapitre en entier, formules et figures comprises, avec le tuteur, les fiches, les QCM et les exercices.

Lire la suite du cours

En accès libre, sans inscription.

Exercices corrigés de ce chapitre

Lire la suite du cours →