Pont à sens unique avec des voitures générées par un host éloigné


 4.8.0.1 Le pont - ressource (moniteur). Les voitures le prennent s'il est libre ou bien si sur le pont il y a des voitures circulent en même direction, exigence d'alterner les voitures de droite et de gauche.

public class Bridge {
    private int nVh, countSeq, maxCount;
    private boolean open;
    Bridge(int maxCount){
        nVh = countSeq=0;
        open = true;
        this.maxCount=maxCount;
    }
    synchronized public int brN(){
        return nVh;
    }
    synchronized public void takeB(boolean lr ){
        boolean waiting=false;   //to print waiting only once for vehicle
        while((nVh>0)&& (lr==true)||
                (nVh<0) && (lr==false)|| !open){
            if(!waiting) {
                System.out.println("\t"+Thread.currentThread().getName()+" waiting");
                waiting=true;
            }
            try{     wait();   }
            catch(InterruptedException e){
                System.err.println(e);
            }
        }
        countSeq++;
        if (lr) nVh--;
        else nVh++;
        System.out.println(Thread.currentThread().getName()+" on the bridge in the same direction: "+countSeq);
        if (countSeq==maxCount){open = false; System.out.println("The bridge is closed");}
    }
    synchronized public void leaveB(boolean lr ){
        if (nVh>0) nVh--;
        else nVh++;
        System.out.println("\t\t"+Thread.currentThread().getName()+" leave the bridge");
        if(nVh==0){countSeq=0;open = true; System.out.println("The bridge is open");}
        notifyAll();
    }
}

 4.8.0.2 Voiture locale ou remote (Thread). 

Les paramètres du constructeur sont : le nom (null pour locale), direction, pont, et PrintWriter (null pour locale). Les voitures locales sont générées par Circ, tandis que les voitures éloignées sont générées par des threads ServOneVehicle sur demandes des clients.

//for local in constructor's parameter:  name=out=null
import java.io.PrintWriter;

public class Vehicle extends Thread{
  private boolean lr;
  private Bridge b;
  private String name;
  private static int num;
  private PrintWriter out;
  Vehicle(String name,boolean lr, Bridge b, PrintWriter out){
      this.lr=lr;
      this.b = b;
      this.out=out;
      if(name==null)this.name = "V "+ ++num + (lr?" left->":" <-right");  //local vehicle
      else this.name = "\t\t\t"+name + " remote"; //remote vehicle
      super.setName(this.name);
  }
  public void run(){
      try {
          sleep(3000);
      } catch (InterruptedException e){}
      if (out!=null){         //remote
          out.println(name+ " wait to take the bridge");
      }
      b.takeB(lr);
      if (out!=null){         //remote
          out.println(name+ " is on the bridge");
      }
      try {
          sleep(6000);
      } catch (InterruptedException e){}
      b.leaveB(lr);
      if(out!=null)out.println(name+" leave the bridge");          //remote
  }
}

 4.8.0.3 Serveur. Ecoute sur le port 8082. S’il y a demande il lance un thread pour servir  un client éloigné - ServeOneVehicle.

import java.io.*;
import java.net.*;
public class Server extends Thread{
    private static final int PORT = 8082;
    private ServerSocket s=null;
    private Bridge b;
    Server(Bridge b){
        this.b=b;
    }
    public void run(){
        try {
            s = new ServerSocket(PORT);
            System.out.println("Server Started");
            while(true) {
                // Blocks until a connection occurs:
                Socket socket = s.accept();
                try {
                    new ServeOneVehicle(socket,b);
                } catch(IOException e) {
                    // If it fails, close the socket,
                    // otherwise the thread will close it:
                    socket.close();
                }
            }
        }
        catch(Exception ioe){}
        try {
            s.close();
        }
        catch(Exception ioe){}       
    }
}

 4.8.0.4 Thread pour servir  un client éloigné. Attend une demande du client éloigné pour générer une voiture éloigné.

Protocole – deux lignes. La première contient le nom du client, la deuxième – direction de circulation (left ou right). Les lignes suivantes - nouvelles directions de circulation, la ligne vide - fin de séance


import java.io.*;
import java.net.*;
class ServeOneVehicle extends Thread {
    private Socket socket;
    private BufferedReader in;
    private PrintWriter out;
    private Bridge b;
    private String name="";
    public ServeOneVehicle(Socket s, Bridge b)  throws IOException {
        socket = s;
        in = new BufferedReader(
                new InputStreamReader(
                  socket.getInputStream()));
        out =   new PrintWriter(
                new BufferedWriter(  new OutputStreamWriter(
                        socket.getOutputStream())),true);
        this.b=b;
        System.out.println("\t\t\tnew remote connection");
        start();    // Calls run()
  }
  public void run() {
      String leftToRight;
      boolean lr;
    try {
        name = in.readLine();
        while (true) {
             leftToRight = in.readLine();
             if (leftToRight.equals("END")) break;
             if(leftToRight.equalsIgnoreCase("Left"))lr=true;
             else lr=false;
             (new Vehicle(name,lr, b,out)).start();       
        }
        System.out.println("closing connection to "+name);
    } catch (IOException e) {  }
   finally {
      try {
        socket.close();
      } catch(IOException e) {}
    }
  }
}
 


 4.8.0.5 L'application principale. 

Démarre le serveur d'attente des   clients éligné et  génére de manière cyclique  de voitures locales en serie par 10. 

public class Circ {
    public static void main(String arg[]){
       
        Bridge b = new Bridge(3);
        (new Server(b)).start();
        for(int i = 1; ; i++){
            (new Vehicle(null,Math.random()>0.5?true:false, b,null)).start();
            try{
                Thread.sleep(1000);
            }catch (InterruptedException e){}
            if((i%10)==0)
                try{
                    Thread.sleep(10000);
                }catch (InterruptedException e){}
        }
    }
}

 4.8.0.6 Le client éloigné.

Demande le nom  et  des consecutives  directions de passage d'une nouvelle voiture éloignée. Fin après une ligne vide.    Attend  les messages de la voiture pour l'entrée et la sortie du pont et les affiche sur la console.

import java.net.*;
import java.io.*;
public class RemVehicleClient {
    private static final int PORT = 8082;
    private static String name;
    public static void main(String[] args)throws IOException {
        String server = null;
        InetAddress addr =  InetAddress.getByName(server);
        System.out.println("addr = " + addr);
        Socket socket = new Socket(addr, PORT);                   
                    //Socket s=new Socket(); //s.connect(new  InetSocketAddress(host,port),timeout);
        // Guard everything in a try-finally to make       
        // sure that the socket is closed:
        try {
            System.out.println("socket = " + socket);
            BufferedReader in =
                    new BufferedReader(
                            new InputStreamReader(socket.getInputStream()));
            BufferedReader sin =  new BufferedReader(
                    new InputStreamReader(System.in));

            // Output is automatically flushed
            // by PrintWriter:
            PrintWriter out =   new PrintWriter(
                    new BufferedWriter(  new OutputStreamWriter(
                            socket.getOutputStream())),true);
            System.out.print("Your name please:");
            name = sin.readLine();
            out.println(name);
            for(;;) {
                System.out.print("input L(left->right) or R(right->left) [empty for finish] :");
                String s = sin.readLine();
                if(s.length()==0) break;
                if(!(s.equalsIgnoreCase("L"))&&!(s.equalsIgnoreCase("R"))) {
                    System.out.println("L or R or 'Enter' please");
                    continue;
                }

                out.println(s.equalsIgnoreCase("L")?"Left":"Right");
                System.out.println(in.readLine());    // wait to take the bridge
                System.out.println(in.readLine());    // take the bridge
                System.out.println(in.readLine());    // leave the bridge
            }
            out.println("END");
        }
        finally {
            System.out.println("closing...");
            socket.close();
        }
    }
}

 4.8.0.7 Exercice: Modifier le programme afin que le client reçoive une annonce supplémentaire quand la voiture éloignée est créée dans le serveur.