Systèmes distribués
Ingéniérie mathématique et informatique - S3 Je matin


[Les threads en Java] [TP]


Séance 2 : protocole TCP

Sockets, côté client

Java permet la communication entre deux processus par un mécanisme de flot basé sur le protocole TCP, au moyens des sockets. Ce sont des objets de la classe Socket, dont les constructeurs et certaines méthodes peuvent déclencher l'exception IOException. Un socket est construit à partir de l'adresse de transport distante :

  InetAddress a = InetAddress.getByName("www.enpc.fr");
  Socket httpSocket = new Socket(a, 80);
  Socket localDateSocket = new Socket("localhost", 13);

Les méthodes getInetAddress() et getPort() d'une part, getLocalAddress() et getLocalPort(), d'autre part permettent d'obtenir l'adresse de transport distante (spécifiée en argument du constructeur) et l'adresse de transport locale.

La méthode getInputStream() de la classe Socket permet de lire un flot de données à partir d'un socket ; la méthode getOutputStream() permet d'écrire un flot de données à destination d'un socket. Un programme peut se connecter à un serveur distant en créant un socket (client) et en utilisant les flots d'entrée et de sortie de ce socket. La création de ce socket exprime une demande d'un service de transport TCP, qui devra être satisfaite par une connexion mise en place par la machine distante. Le programme suivant se connecte au port 13 de la machine locale à l'aide d'un socket, reçoit sur le flot d'entrée de ce socket une chaîne de caractères, ferme le flot et ferme la connexion :

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

class ClientDate {
  public static void main(String[] args) 
    throws IOException {
    
    Socket localDateSocket = new Socket("localhost", 13);
    BufferedReader reponse = 
      new BufferedReader(
        new InputStreamReader(
	  localDateSocket.getInputStream()));
    String date = reponse.readLine();
    System.out.println("Date : " + date);
    reponse.close();
    localDateSocket.close();
  }
}

Serveurs itératifs

Le processus serveur correspondant au client ClientDate doit écouter en permanence sur un port (on doit choisir un port supérieur ou égal à 1024, plutôt que 13, qui est le port du serveur time standard). Cette écoute est réalisée par un objet de la classe ServerSocket. Quand un autre processus demande une connection à ce port, la méthode accept() de l'objet serveur est invoquée ; celle-ci retourne un socket qui réalise la connexion demandée avec le socket client. Contrairement au socket côté client, celui côté serveur n'est pas créé par un constructeur.

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

public class ServeurDate {

 final static int PORTDATE = 1314;    

  public static void main(String[] args) 
    throws IOException {

    ServerSocket serveur = new ServerSocket(PORTDATE);
    Socket connexion;
    PrintWriter p;
    
    while (true) {
      connexion = serveur.accept();
      p = new PrintWriter(connexion.getOutputStream());
      p.println(new java.util.Date());
      p.flush();
      connexion.close();
    }
  }
}

Une autre forme du constructeur permet de spécifier le taille maximum de la file d'attente des demandes de connexions :

ServerSocket serveur = new ServerSocket(PORTDATE, 16);

Le type du serveur précédent est dit itératif, parce que les demandes de connexion sont satisfaites l'une après l'autre.

[Systèmes distribués]