Communication en multicast                  

Communication en multicast

     

Le concept de multicast est apparu il y a une quinzaine d'années. Nous n'expliquerons pas son fonctionnement technique, mais uniquement son utilisation. Il permet à un groupe de machines de communiquer de telle sorte que chaque message envoyé soit reçu par l'ensemble des membres du groupe. Le groupe utilise pour communiquer une adresse IP virtuelle ; cette adresse doit nécessairement être comprise entre 224.0.1.0 et 239.255.255.255 et n'est pas l'adresse d'une machine réelle ; on choisit également un numéro de port compris entre 1024 et 65535 qui sera le numéro de port sur lequel les messages seront attendus.

Pour recevoir les messages du groupe, il faut, dans le programme Java, disposer d'un socket relié au port retenu ; on utilise pour cela la classe MulticastSocket qui hérite de la classe DatagramSocket ; il faut alors que ce socket indique qu'il joint le groupe, avec la méthode adéquate, en indiquant l'adresse IP virtuelle de ce groupe. Après cela, il suffit d'attendre des datagrammes par le socket, de la même façon que pour toute réception de datagramme.

Pour envoyer des messages au groupe, il faut construire un datagramme en indiquant l'adresse IP virtuelle et en spécifiant le port de réception. Par ailleurs, il faut préciser au socket qui servira à l'émission (qui peut être le même que celui utilisé pour la réception) le TTL (Time To Live) ; celui-ci indique la portée de l'émission et correspond au nombre de routeurs multicast que le datagramme pourra traverser ; un TTL de 1 ne permet que d'atteindre les machines du réseau local, avec un TTL de 15, on atteint l'ensemble du site, pour un TTL de 31, la région, pour un TTL de 47 le pays, pour un TTL de 63 le continent et pour un TTL de 127 le monde entier ; par défaut, le TTL vaut 1.

Nous donnons ci-dessous un exemple de programme qui permet de communiquer entre un groupe de personnes disposant de différentes machines. Les messages sont envoyés et reçus dans la fenêtre d'exécution. Le programme est lancé en indiquant sur la ligne de commande un identificateur qui permet aux membres du groupe de savoir qui est l'auteur de l'envoi.


import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;

class Recepteur extends Thread {
   InetAddress  groupeIP;
   int port;
   String nom;
   MulticastSocket socketReception;

   Recepteur(InetAddress groupeIP, int port, String nom)  throws Exception { 
	   this.groupeIP = groupeIP;
	   this.port = port;
	   this.nom = nom;
	   socketReception = new MulticastSocket(port);
	   socketReception.joinGroup(groupeIP);
	   start();
  }

  public void run() {
    DatagramPacket message;
    byte[] contenuMessage;
    String texte;
    ByteArrayInputStream lecteur;
    
    while(true) {
		  contenuMessage = new byte[1024];
		  message = new DatagramPacket(contenuMessage, contenuMessage.length);
		  try {
	              socketReception.receive(message);
	              texte = (new DataInputStream(new ByteArrayInputStream(contenuMessage))).readUTF();
	       if (!texte.startsWith(nom)) continue;
	       System.out.println(texte);
		  }
		  catch(Exception exc) {
	    		System.out.println(exc);
		  }
    }
  }
}

class Emetteur extends Thread{
   InetAddress  groupeIP;
   int port;
   MulticastSocket socketEmission;
   String nom;
  
   Emetteur(InetAddress groupeIP, int port, String nom) throws Exception {
      this.groupeIP = groupeIP;
      this.port = port;
      this.nom = nom;
      socketEmission = new MulticastSocket();
      socketEmission.setTimeToLive(15); // pour un site
      start();
  }
    
  public void run() {
    BufferedReader entreeClavier;
    
    try {
       entreeClavier = new BufferedReader(new InputStreamReader(System.in));
       while(true) {
			  String texte = entreeClavier.readLine();
			  emettre(texte);
       }
    }
    catch (Exception exc) {
       System.out.println(exc);
    }
  } 

  void emettre(String texte) throws Exception {
		byte[] contenuMessage;
		DatagramPacket message;
	
		ByteArrayOutputStream sortie = new ByteArrayOutputStream(); 
		texte = nom + " : " + texte ;
		(new DataOutputStream(sortie)).writeUTF(texte); 
		contenuMessage = sortie.toByteArray();
		message = new DatagramPacket(contenuMessage, contenuMessage.length, groupeIP, port);
		socketEmission.send(message);
  }
}

class Multicast {
   public static void main(String[] arg) throws Exception{ 
		String nom = arg[0];
		InetAddress groupeIP = InetAddress.getByName("239.255.80.84");
		int port = 8084; 
		new Emetteur(groupeIP, port, nom);
		new Recepteur(groupeIP, port, nom);
   }
}

Vous pouvez accéder à :


socketReception = new MulticastSocket(port); : on demande de construire un socket lié au port indiqué par l'argument.
socketReception.joinGroup(groupeIP); : par cette instruction, on demande d'être ajouté au groupe des personnes recevant les messages du groupe dont l'adresse virtuelle correspond à groupeIP. L'instruction leaveGroup permettrait de quitter le groupe.
if (!texte.startsWith(nom)) continue; : sans cette instruction, une personne envoyant un message recevrait son propre message, ce qu'on a souhaité éviter ici.
socketEmission.setTimeToLive(15); : en l'absence de cette instruction, le groupe serait restreint au réseau local.

© Irène Charon, TéléParisTech 2011