MokaByte Numero 27  -  Febbraio 1999
Un desktop remoto
di 
Andrea 
Musumeci
Lanciamo tramite RMI delle applicazioni su altre macchine della rete



 Vediamo come realizzare un architettura software che ci permetterà di gestire al meglio la nostra rete utilizzando un unico 'terminale'.

Da alcuni giorni ho installato anche nella mia postazione di lavoro e studio casalinga  una rete economica tra i miei PC; dovendo testare alcune mie applicazioni che lavorano in Internet avevo bisogno di lanciare serverHTTP su una macchina, serverDatabase e altro software e su un altra macchina progettare le mie applicazioni.
Chiarite quindi le mie esigenze ho iniziato a scrivere poco codice che sfruttava RMI e che mi permetteva di evitare continui cambi di tastiera, mouse e scrivania e rimanendo seduto nella mia postazione di lavoro, lanciare applicazioni sull'altro PC.
Ammetto che inizialmente sfruttai l'idea solamente per lanciare un programma chiamato winAmp passandogli come parametri in ingresso il path completo della canzone che doveva 'suonarmi'; modificai in seguito il client e iniziai a lanciare anche la televisione (non sono un pazzo amante dell'hardware 'inutile', ma ho una scrivania super_occupata e anche una TV vera mi avrebbe soltanto dato il 'biglietto di via' da parte dei miei genitori...). 
Portai in ufficio questo mio strano toollettino (un piccolo tool) e l'idea piacque: modificammo poche cosine aggiungendo ad esempio la possibilità di chiudere l'applicazione da remoto e creammo un adeguata interfaccia grafica.
In questo articolo ovviamente non pubblicherò il codice del tool che io e i miei colleghi utilizziamo per lavoro, ma metterò on-line quello dal quale sono partito.
 

Il lato server

Iniziamo col descrivere cosa il server (di programmi) dovrà fare:

l'oggetto dovrà rendere disponibili alcuni dei suoi metodi sulla rete pubblicandoli nel registro RMI (rmiregistry) [in questo caso la lista dei metodi non sarà molto lunga in quanto esso dovrà solo lanciare dei processi con una exec sul un oggetto di tipo Runtime]
Codifichiamo dunque queste idee in un'interfaccia (che dovrà estendere Remote per l'uso tramite RMI):
 

//----------------------------------------------------------------------------

//

// Module : ServerDT.java

//

// Description : interfaccia remota per il ServerDeskTop

//

// Product : RemoteDesktop

//

// Author : Andrea.Musumeci@novara.alpcom.it

//

// Date  : dicembre, 1998

//

// Copyright : ISA Italian Software Agency SRL - freeware per usi non commerciali

//

//----------------------------------------------------------------------------

package com.isa.rmi.RemoteDesktop;

public interface ServerDT extends java.rmi.Remote {

boolean execute(String command) throws java.rmi.RemoteException;

}
 

Ed ora implementiamo il tutto in un'adeguata classe:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

//----------------------------------------------------------------------------

//

// Module : ServerDTImpl.java

//

// Description : classe ServerDTImpl

//

// Product : RemoteDesktop

//

// Author : Andrea.Musumeci@novara.alpcom.it

//

// Date  : dicembre, 1998

//

// Copyright : ISA Italian Software Agency SRL - freeware per usi non commerciali

//----------------------------------------------------------------------------

package com.isa.rmi.RemoteDesktop;

import java.net.URL;

import java.rmi.*;

import java.rmi.server.*;

import java.rmi.registry.LocateRegistry;

import java.rmi.server.UnicastRemoteObject;

import java.util.*;

import java.io.*;

import java.net.*;

import java.lang.*;

public class ServerDTImpl 

extends UnicastRemoteObject implements ServerDT, java.io.Serializable

{

 final String nameServerDT="RemoteDesktop";

 java.lang.Runtime rt;

 /***********/

 /* costruttore */

 /***********/

 public ServerDTImpl() throws java.rmi.RemoteException

  {

  super();

  System.out.println("####################");

  System.out.println("RemoteDesktop started");

  rt = java.lang.Runtime.getRuntime();

  System.out.println("RemoteDesktop: runtime done");

  }

public synchronized boolean execute (String command) throws java.rmi.RemoteException

 {

 try

  {

  System.out.println("RemoteDesktop: executing: "+command);

  rt.exec(command);

  }

 catch (Exception e)

  {

  System.out.println("ServerDT: an exception occurred:");

  e.printStackTrace();

  return false;

  }

  return true;

 }

 /*******/

 /* main  */

 /*******/

 public static void main(String args[])

  {

   int port=1099;

  try

   {

    System.setSecurityManager(new RMISecurityManager());

    System.out.print("RemoteDesktop version 1.0 ");

    System.out.println("Created by Andrea.Musumeci@novara.alpcom.it");

    System.out.println("RemoteDesktop.main: creating registry at port "+port);

    LocateRegistry.createRegistry(port);

    ServerDTImpl serverDT=new ServerDTImpl();

    System.out.println("RemoteDesktop.main: creating server");

    System.out.println("RemoteDesktop.main: binding server ");

    Naming.rebind("//:"+port+"/"+"RemoteDesktop", serverDT);

    System.out.println("RemoteDesktop.main: done");

   }

   catch (Exception e)

    {

     System.out.println("RemoteDesktop: an exception occurred:");

     e.printStackTrace();

     System.exit(1);

    }

   }//fine main

}//fine class ServerDTImpl

Ed ora creiamo la classe ClientDTImpl che avrà il compito di sfruttare i metodi del serverDTImpl:
 

//----------------------------------------------------------------------------

//

// Module : ClientDTImpl.java

//

// Description : ClientDTImpl

//

// Product : RemoteDesktop

//

// Author : Andrea.Musumeci@novara.alpcom.it

//

// Date  : dicembre, 1998

//

// Copyright : ISA Italian Software Agency SRL

//----------------------------------------------------------------------------

package com.isa.rmi.RemoteDesktop;

import java.util.*;

import java.awt.*;

import java.awt.event.*;

import java.rmi.*;

import java.rmi.server.*;

import java.net.*;

import java.io.*;

public class ClientDTImpl extends Object implements java.io.Serializable

  {

  String nameRemoteDesktop = "RemoteDesktop";

  URL UrlBase;

  int port;

  ServerDT serverDT=null;

 public ClientDTImpl(URL base,int port)

  {

  this.port=port;

  UrlBase=base;

  }

 public void connectRemoteDesktop()

  {

  try {

   String serverName = "";

   serverName = "//" + UrlBase.getHost() + ":" +port+ "/"+nameRemoteDesktop;

   System.out.println("I am looking for "+serverName);

   serverDT = (ServerDT) Naming.lookup(serverName);

   if (serverDT==null) System.out.println("RemoteDesktop not found");

   }

  catch (Exception e)

      {

   System.out.println("An exception occurred:");

   e.printStackTrace();

     }

  }

 public boolean execute(String command)

 {

  try{

   return serverDT.execute(command);

    }

  catch (Exception e)

  {

   System.out.println("an exception occurred:");

   e.printStackTrace();

  }

return false;

}

}

Facciamo in modo quindi di lanciare il serverDTImpl da una classe esterna del package:
 

//----------------------------------------------------------------------------

//

// Module : IsaServerDT.java

//

// Description : IsaServerDT

//

// Product : RemoteDesktop

//

// Author : Andrea.Musumeci@novara.alpcom.it

//

// Date  : dicembre, 1998

//

// Copyright : ISA Italian Software Agency SRL

//----------------------------------------------------------------------------

import com.isa.rmi.RemoteDesktop.*;

import java.net.URL;

import java.rmi.*;

import java.rmi.server.*;

import java.rmi.registry.LocateRegistry;

import java.rmi.server.UnicastRemoteObject;

import java.net.*;

public class IsaServerDT

{

/*questa classe server solo a lanciare la classe ServerDTImpl */

 /*******/

 /* main */

 /*******/

 public static void main(String args[])

  {

   int port=1099;

  try

   {

    System.setSecurityManager(new RMISecurityManager());

    System.out.println("RemoteDesktop - version 1.0");

    System.out.println(" created by Andrea.Musumeci@novara.alpcom.it");

    System.out.println("RemoteDesktop.main: creating registry at port "+port);

    LocateRegistry.createRegistry(port);

    ServerDTImpl serverDT=new ServerDTImpl();

    System.out.println("RemoteDesktop.main: creating server");

    System.out.println("RemoteDesktop.main: binding server ");

    Naming.rebind("//:"+port+"/"+"RemoteDesktop", serverDT);

    System.out.println("RemoteDesktop.main: done");

   }

   catch (Exception e)

    {

     System.out.println("ServerDT: an exception occurred:");

     e.printStackTrace();

     System.exit(1);

    }

   }//fine main

}//fine class IsaServerDT

Adesso basta creare un'applicazione che sia in grado di sfruttare tramite RMI i metodi del ServerDT utilizzando la classe ClientDTImpl.
 

//----------------------------------------------------------------------------

//

// Module : IsaClientDTApplication.java

//

// Description : little demo to use remoteDesktop in an application

//

// Product : remoteDesktop

//

// Author : Andrea Musumeci

//

// Date  : Dicembre, 1998

//

// Copyright : ISA Italian Software Agency SRL

//----------------------------------------------------------------------------

import com.isa.rmi.RemoteDesktop.*;

import java.util.*;

import java.net.*;

import java.io.*;

public class IsaClientDTApplication

  {

  ClientDTImpl clientDT;

  public String host="127.0.0.1";

  public int port=1099;

 public IsaClientDTApplication(String host,int port, String command)

 {

 System.out.println("I'm creating an object clientDT");

  try

  {

   String urlString="http://"+host;

   URL url=new URL(urlString);//inserire l'http del serverRMI

   clientDT = new ClientDTImpl(url,port);

   System.out.println("Object clientDT created.");

   clientDT.connectRemoteDesktop();

   boolean allOK = clientDT.execute(command);

  if (allOK)  System.out.println("Commad executed.");

        else System.out.println("Commad not executed.");

  }

  catch (Exception e)

  {

   System.out.println("Errors found");

  }

  System.exit(0);

 }

  public static void main(String args[])

 { if (args.length!=3)

   {

    System.out.println("USO: java IsaClientDTApplication host port command");

   }

   else

    {

     int port=(new Integer(args[1]) ).intValue();

     try

      {

       System.out.println("ora di start: "+(new Date()).toString());

       IsaClientDTApplication isa=new IsaClientDTApplication(args[0],port,args[2]);

      }

     catch (Exception e)

      {

       e.printStackTrace();

      }

    }

  }//fine main

}

Adesso possiamo tranquillamente compilare il tutto ricordando di generare tramite rmic i file di stub e di skel per il serverDT
 
javac *.java

rmic com.isa.rmi.RemoteDesktop.ServerDTImpl -dstub . -dskel .

jar cvf0 RemoteDesktop.jar com

e quindi lanciamo il serverDT proviamo il client:
 
java IsaServerDT
quando il server restituisce il messaggio 'done' allora digitiamo:
 
java IsaClientDTApplication 127.0.0.1 1099 "c:\windows\notepad"
Semplice no?
Ricordate ovviamente che i parametri del client devono essere personalizzati; è chiaro che la parte client e la parte server potrebbero essere dotate di un'interfaccia user friendly, magari pensata con swing, ma questo andrebbe al di la degli scopi di questo articolo ossia di cercare di far affezionare sempre il maggior numero di programmatori a RMI: la via più semplice (secondo me) verso la programmazione distribuita.
 

Per i più pigroni ecco la struttura completa dell'esempio...
 
Andrea Musumeci e' studente universitario del dipoma in Informatica presso l'Universita' degli Studi di Milano. Si occupa inoltre di programmazione java presso la I.S.A. - italian software agency - di Baveno e cura il mirror di mokabyte di Novara (mokabyte.novara.alpcom.it). Lo potete contattare via e-mail a Andrea.Musumeci@novara.alpcom.it.


 
 
 
 

MokaByte Web  1999 - www.mokabyte.it

MokaByte ricerca nuovi collaboratori. 
Chi volesse mettersi in contatto con noi può farlo scrivendo a mokainfo@mokabyte.it