Socket :
Communication via le réseau

un premier socket

Source de SocketClient1.java
import java.io.*;
import java.net.*;
public class SocketClient1 { 
  public static void main(String args[]) {
    if (args.length != 2)
      System.out.println("usage : SocketClient1 hote port");
    else {
      Socket soc = null;
      String hote = args[0];
      int port = Integer.valueOf(args[1]).intValue();
      try {
        soc = new Socket(hote, port);
        BufferedReader socIn = new BufferedReader(
                 new InputStreamReader(soc.getInputStream()));
        String ligne;
        while ((ligne = socIn.readLine()) !=  null)
          System.out.println(ligne);
      } catch (UnknownHostException e) {
        System.out.println("hote "+ hote +" inconnu : "+e.getMessage());
      } catch (IOException e) {
        System.out.println("erreur entree/sortie : "+e.getMessage());
      }
    }
  }
}

EXECUTION avec 2 terminaux
$ javac DayTimeServer.java
$ java DayTimeServer
start DayTime server sur port : 1313



$ java SocketClient1 localhost 1313
Tue Dec 13 12:16:57 2005

Les lignes de la classe :

lecture et écriture dans un socket

Source de ClientEcho.java
import java.io.*;
import java.net.*;
import java.util.Scanner;
public class ClientEcho {
  public static void main(String[] args) throws IOException {
    if (args.length != 1) {
      System.out.println("Usage : java ClientEcho hostName" );
      System.exit(1);
    }
    String hostName = args[0]; 
    Socket sock = null;
    PrintWriter sockOut = null;
    BufferedReader sockIn = null;
    
    try {
      sock = new Socket(hostName, 7777);
      sockOut = new PrintWriter(sock.getOutputStream(), true);
      sockIn = new BufferedReader(new InputStreamReader(
                                      sock.getInputStream()));
    } catch (UnknownHostException e) {
      System.err.println("host non atteignable : "+hostName);
      System.exit(1);
    } catch (IOException e) {
      System.err.println("connection impossible/cassee avec : "+hostName);
      System.exit(1);
    }
    System.out.println("tapez q pour terminer"); 
    Scanner scan = new Scanner(System.in);
    String message = scan.next().toLowerCase();
    while (! message.equals("q")) {
      sockOut.println(message);
      String recu = sockIn.readLine();
      if (recu == null) {
        System.out.println("erreur de connection");
        break;
      }
      System.out.println("echo: " + recu.trim());
      message = scan.next().toLowerCase();    
    }
    
    sockOut.close();
    sockIn.close();
    sock.close();
  }
}

EXECUTION sur plusieurs terminaux
$ javac ServeurEcho.java 
$ java ServeurEcho
      



$ java ClientEcho localhost
tapez q pour terminer coucou echo: coucou bonjour echo: bonjour q $ java ClientEcho localhost world echo: world ...

 Les lignes de la classe :

 

  • Il faut mettre préalablement en exécution un serveur d'échos
    donc lancez ServeurEcho sur une console différente
  • on peut exécuter de nouveaux clients tant que le serveur fonctionne
  • par contre, un seul client est servi à la fois
  • si on arrete le serveur par un <ctrl>C, un message "erreur de connection" est affiché
  • si on exécute le client sans le serveur, un message "connection impossible avec ..." est affiché

Communication par socket dans le "kernel"

class Socket

byte et char : caractère transmis et caractère JAVA

Pour les caractères, le langage JAVA utilise le type char basé sur l'Unicode codé sur 16 bits.
Les transmissions sur les réseaux est basé sur l'octet : 8 bits. Il est commode d'y transmettre des caractères ASCII (7 bits).
Les methodes de télécommunication de JAVA sont donc basées sur le transfert d'octets (byte).
Voici comment convertir un String en byte[ ] et réciproquement :
byte[] buffer = new byte[100];
String chaine = "Ceci est une chaine";  
byte[] message ;
//        conversion String vers byte[]
message = chaine.getBytes();    
//        conversion byte[] vers String
chaine = new String(message);    
//        idem mais un morceau du buffer
chaine = new String(buffer, 3, 25);

Le serveur d'Echo

Source de ServerEcho.java
import java.net.*;
import java.io.*;
class ServerEcho {  
  public static void main(String args[]) {
    ServerSocket server = null;
    try {
      server = new ServerSocket(7777);
      while (true) {
        Socket sock = server.accept();
        System.out.println("accept");
        PrintWriter sockOut = new PrintWriter(
           sock.getOutputStream(), true);
        BufferedReader sockIn = new BufferedReader(
           new InputStreamReader(sock.getInputStream()));
        String recu;        
        while ((recu = sockIn.readLine()) != null) {
          System.out.println("recu :"+recu);
          sockOut.println(recu);
        }
        sockIn.close();
        sockOut.close();
        sock.close();
      }
    } catch (IOException e) {
      System.out.println(e.getMessage());
    } finally {
        try {
          server.close();
        } catch (IOException e2) {     
          System.out.println(e2.getMessage());
        }
    }
  } 
}

Les lignes de la classe :

  • le programme crée un serveur de socket sur son port 7777
  • puis l'appel à accept() met le server en attente d'une connection d'un client
  • à réception d'une connection d'un client, un socket est crée pour assurer la communication.
  • lorsque le client a fini, le programme ferme le socket avec ce client
  • et se remet en boucle d'attente d'une connection d'un client

EXECUTION
$ java ServerEcho
accept
recu:coucou
recu:bonjour
accept
recu:world
....

La séquence correspond exactement aux demandes des clients ci-dessus.

Tapez <ctrl>C pour arrêter le serveur

class ServerSocket

Les "Schémas"d'écriture des sockets

Lecture et écriture de "plus haut niveau"

InputStream sockIn = socket.getInputStream();
byte[] buffer = new byte[1024];
int lu=0;
try {
  lu = sockIn.read(buffer);
  if (lu == -1)
    // fin de flot atteinte 
  else  
  {
    Scanner scan = new Scanner(new String(buffer));
    String premierMot = scan.next());
    String secondMot = scan.next());
    if (scan.hasNextInt())
      int entier = scan.nextInt());
    else
      String troisieme = scan.next());
    if (scan.hasNextFloat())
      float reel = scan.nextFloat());
    else
      String quatrieme = scan.next());
    if (scan.hasNextBoolean())
      boolean booleen = scan.nextBoolean());
    else
      String cinquieme = scan.next());
  }
} catch (IOException e) {
    // lecture impossible }
} catch (IllegalStateException) { 
    // si le scanner est fermé
} catch (InputMismatchException) { 
   // si le type de donnée est incompatible
} catch (NoSuchElementException) { 
   // s'il n'y a pas de donnée }

Transmission d'objet par réseau

Mise en place d'un ToutouService

Nous utilisons une classe Chien5.java :
public class Chien5 
       implements Serializable {
  String nom;
  String aboiement;
  int nombrePuce;
  Chien5(String s, String a, int i) 
  int getNombrePuce() 
  String getNom() 
  void setNombrePuce(int p) 
  void seGratte(int fois) 
  public boolean equals(Object autre) 
  public String toString() 
  String aboie()
Source de ClientChien.java
import java.io.*;
import java.net.*;
public class ClientChien {
  public static void main(String[] args) throws IOException {
    if (args.length != 2) {
      System.out.println("Usage : java ClientChien hostName nom_chien" );
      System.exit(1);
    }
    String hostName = args[0]; 
    String chienDemandé = args[1]; 
    Socket sock = null;
    PrintWriter sockOut = null;
    ObjectInputStream sockIn = null;
    
    try {
      sock = new Socket(hostName, 7777);
      sockOut = new PrintWriter(sock.getOutputStream(), true);
      sockIn = new ObjectInputStream(sock.getInputStream());
    } catch (UnknownHostException e) {
      System.err.println("host non atteignable : "+hostName);
      System.exit(1);
    } catch (IOException e) {
      System.err.println("connection impossible avec : "+hostName);
      System.exit(1);
    }
    sockOut.println(chienDemandé);
    try {
      Object recu = sockIn.readObject();
      if (recu == null) 
        System.out.println("erreur de connection");
      else if (recu.getClass().equals(Chien5.class)) {
        Chien5 chien = (Chien5)recu;
        System.out.println("recu: " + chien);  
      }
    } catch (ClassNotFoundException e) {
      System.err.println("Classe inconnue : "+hostName);
      System.exit(1);
    }  
   
    sockOut.close();
    sockIn.close();
    sock.close();
  }
}
Source de ServerChien.java
import java.net.*;
import java.io.*;
class ServerChien {
  public static void main(String args[]) {
    Chien5[] tabChien = {
          new Chien5("medor", "wouf", 3),
          new Chien5("milou", "wouah", 0),
          new Chien5("cerbere", "grrr", 12)
    };
      
    ServerSocket server = null;
    try {
      server = new ServerSocket(7777);
      while (true) {
        Socket sock = server.accept();
        System.out.println("accept");
         ObjectOutputStream sockOut = 
               new  ObjectOutputStream(sock.getOutputStream());
        BufferedReader sockIn = new BufferedReader(
               new InputStreamReader(sock.getInputStream()));
        String recu;        
        while ((recu = sockIn.readLine()) != null) {
          System.out.println("recu :"+recu);
          String nom = recu.trim();
          for (int i=0; i<tabChien.length; i++) 
            if (tabChien[i].getNom().equals(nom)) {
              sockOut.writeObject(tabChien[i]);
              break;
          }
        }
        sockOut.close();
        sock.close();
      }
    } catch (IOException e) {
      System.out.println(e.getMessage());
      try {
        server.close();
      } catch (IOException e2) {     
        System.out.println(e2.getMessage());
      }
    }
  } 
}

EXECUTION avec 2 terminaux

$ javac Chien5.java
$ javac ServerChien.java
$ java ServerChien
accept


recu : milou






$ javac ClientChien.java

$ java ClientChien localhost milou
recu: chien : milou aboie wouah et a 0 puces.

Les lignes de la classe :

++ Ecriture ou lecture sur socket fermé

source de  ServerTestSocket :
import java.net.*;
import java.io.*;
import java.util.*;
class ServerTestSocket {
  
  public static void main(String args[]) {
    ServerSocket server = null;
    Socket sock = null;
    OutputStream sockOut = null;
    try {
      server = new ServerSocket(7777);
    } catch (IOException e1) {
      System.out.println("impossible creer server : "+e1.getMessage());
    }
    System.out.println("server ecoute sur port 7777");
    Scanner scan = new Scanner(System.in);
    String message = "";
    message = scan.next().trim().toLowerCase();   
    while (! message.equals("quit")) {
      try {
        sock = server.accept();
      } catch (IOException e2) {
        System.out.println("server accept erreur : "+e2.getMessage());
        System.exit(1);
      }
      try {
        sockOut = sock.getOutputStream();
      } catch (IOException e6) {
        System.out.println("server sock.getOutputStream() erreur : "
                            +e6.getMessage());
        System.exit(1);
      }
      System.out.println("server accept connection d'un client");
      byte[] buffer = new byte[1024];
      while ((! message.equals("quit"))&&(! message.equals("close"))) {
        buffer = message.getBytes(); 
        try {
          sockOut.write(buffer,0,message.length());
          sockOut.flush();
        } catch (IOException e3) {
          System.out.println("server write error :(fermeture du client?)"
                             +e3.getMessage());
        }
        message = scan.next().trim().toLowerCase();   
      }  
      if ( message.equals("close")) 
        try {
          sockOut.close();
          sock.close();
          message = scan.next().trim().toLowerCase();  
        } catch (IOException e5) {
          System.out.println("server sockOut ou sock close erreur : "
                             +e5.getMessage());
          System.exit(1);
      }
    }
    try {
      server.close();
    } catch (IOException e4) {     
      System.out.println(e4.getMessage());
    }
  }
}

Les lignes de la classe :

source de  ClientTestSocket :
import java.io.*;
import java.net.*;
import java.util.*;
public class ClientTestSocket {
  public static void main(String[] args)  {
    Socket sock = null;
    InputStream sockIn = null;
    String hote = "localhost";
    if (args.length > 1) {
      System.out.println("usage : ClientTestSocket [hote]");
      System.exit(1);
    } else if (args.length == 1)
      hote = args[0];  
    try {
      sock = new Socket(hote, 7777);
      sockIn = sock.getInputStream();
    } catch (UnknownHostException e) {
      System.err.println(hote + " : host non atteignable");
      System.exit(1);
    } catch (IOException e) {
      System.err.println("connection impossible");
      System.exit(1);
    }
    System.out.println("client connecte a hote :"+hote);
    Scanner scan = new Scanner(System.in);
    String message = scan.next();
    message = message.trim().toLowerCase();
    while ( message.equals("read")) {
      byte[] buffer = new byte[1024];
      int lu=0;
      try {
        lu = sockIn.read(buffer);
      } catch (IOException e3) {     
        System.out.println("erreur sockIn.readLine() :"
                           +e3.getMessage());
      }
      if (lu == -1) 
        System.out.println("fin de flot : recu -1");
      else {
        Scanner scan2 = new Scanner(new String(buffer));
        while (scan2.hasNext())
          System.out.println("client recu : "+scan2.next());
      }
      message = scan.next().trim().toLowerCase();    
    }
    if (message.equals("close")) {    
      try {
        sockIn.close();
      } catch (IOException e4) {     
        System.out.println("erreur sockIn.close() :"
                            +e4.getMessage());
      }
      try {
        sock.close();
      } catch (IOException e5) {     
        System.out.println("erreur sock.close() :"
                            +e5.getMessage());
      }
    }
    while (! message.equals("quit"))     
      message = scan.next().trim().toLowerCase();
  }
}

Les lignes de la classe :

EXECUTION
$ java ServerTestSocket
server ecoute sur port 7777
coucou
server accept connection d'un client

$ java ClientTestSocket
client connecte a hote :localhost
read
client recu : coucou

close
quit
$

encore
unautre
server write error : (fermeture du client ?)Broken pipe
quit

EXECUTION
$ java ServerTestSocket
server ecoute sur port 7777
coucou
server accept connection d'un client

$ java ClientTestSocket
client connecte a hote :localhost
read
client recu : coucou

close

read
fin de flot : recu -1

quit
$

quit
$

exercices