|
Questa parte riguarda la costruzione di un client RPC in java. Creeremo un'applicazione che puo' essere usata sia come stand-alone che come applet nel caso lo volessimo lanciare da un browser. Quando si inizia un'applicazione ONC RPC, la prima cosa da fare è scrivere un'interfaccia XDR. Rappresenta i dati di ingresso che verranno passati al server,il dato di uscita (un servizio rpc puo' mandare un'unico dato per volta al client). Distinct ONC RPC/XDR for Java comprende il linguaggio XDR descritto nel RFC 1832 (XDR: External Data Representation Standard). Per convenzione i files XDR hanno l'estensione .x. 1.1. Il file XDR Il codice qui sotto riportato è un IDL (interface definition language) che chiamero' progetto.x. E' un semplice servizio che preleva delle linee da un testo. Da notare il forte utilizzo da parte di XDR della sintassi C. %/**************************************** %* prova progetto.x * %****************************************/ struct request { int from; int to; }; struct result { int number; string line; struct result *next; }; typedef result *res_list; program PROGETTO_SERVER { version PROGETTO_VERSION { res_list get_line(request) = 1; } = 1; } = 0x20000023; E' diviso in 5 parti: - Commento che inizia con '%'.
- La struct request di input.
- La struct response di output.
- Il typedef res_list corrispondente al result. Il typedef è richiesto necessariamente da XDR affinchè possa tornare un puntatore a Result ..E' infatti non ammessa la dichiarazione di questo tipo : Result *get_line(request) = 1; .Se proprio non si vuole usare un typedef si potrebbe dichiarare il servizio in quest'altro modo: Result get_line(request) = 1; Ovviamente l'implementazione del codice risulterà abbastanza diversa dall'esempio della guida. Lo stesso discorso vale per la request.
- Il progetto PROGETTO_SERVER.
1.2 Il Client java Una volta creato il IDL è sufficiente compilare con Jrpcgen. Il pacchetto Jrpcgen creerà in automatico tutte le classi necessarie per trasformare il nostro codice in un Client RPC.Nel caso di progetto.x, se la sintassi è corretta verranno create le seguenti classi: >>java Jrpcgen progetto.x Jrpcgen V4.0, Copyright 1997 - 2001 by Distinct Corporation progetto.x : writing: request.java writing: result.java writing: res_list.java writing: progetto.java Si tratta di quattro classi, che implementano il client stub collegato al servizio progetto: le prime tre classi rappresentano i dati di input e output e implementano la classe XDRType, la quale contiene le informazioni relative alla conversione dei dati XDR a java; la quarta classe è chiamata stub ed è la descrizione del progetto vero e proprio che contiene la descrizione del servizio get_line. Essa implementa la classe JRPCClient. 1.2.1 Lo Stub JRPC Diamo un occhiata ora allo stub progetto.java. /* ************************************** * Stub JRPC * ****************************************/ import com.distinct.rpc.*; import java.io.IOException; import java.net.InetAddress; /** *This class was automatically generated by Jrpcgen from the RPC/XDR file "progetto.x" <br>. * It defines the client interface to a server implementing the "progetto" interface. */ public class progetto extends JRPCClient { /** Program ID of the interface. */ public static final int PROGETTO_SERVER = 0x20000023; /** * Creates and connects an RPC client for a server that implements the "PartecipazioniRilevanti" interface. * Calls the remote Portmapper in order to get the port of the server. * @param host The host on which the server lives. * @param stream true for a TCP connection, false for UDP. * @exception RPCError When the calls fails for any reason. */ public static final int PROGETTO_VERSION = 1; /** * Creates and connects an RPC client for a server that implements the "progetto" interface. * Calls the remote Portmapper in order to get the server.port * @param host The host on which the server resides. * @param stream true for a TCP connection, false for UDP. * @exception RPCError When the calls fail for any reason. */ public progetto(InetAddress host, boolean stream) throws RPCError { super(host, PROGETTO_SERVER, PROGETTO_VERSION, stream); } /** * Creates and connects an RPC client for a server that implements the "progetto" interface. * The client is connected to a server with a known port. (No interaction with a portmapper) * @param host The host on which the server resides. * @param port The port on which the server listens. * @param stream True for a TCP connection, false for UDP. * @exception RPCError When the calls fail for any reason. */ public progetto(InetAddress host, int port, boolean stream) throws RPCError { super(host, PROGETTO_SERVER, PROGETTO_VERSION, port, stream); } /** * Creates an RPC client for a server that implements the "progetto" interface. * It initializes it with an externally created protocol client object. * @param protocol The protocol object that implements the client connection. */ public progetto(ClientGeneric protocol) { super(protocol); } public static final int get_line = 1; /** * Stub method that invokes the server function "get_line" (version 1). */ public res_list get_line_1(request arg) throws RPCError, IOException { res_list retval = new res_list(); GetClient().Call(get_line, arg, retval); return retval; } }; L'istanza di questa classe manda la chiamata al server. Utilizza il servizio di portmapper per trovare la porta della connessione. Senza entrare in tutti i dettagli possiamo vedere facilmente che questa classe è formata da diverse costanti, tre costruttori e un metodo pubblico get_line_1 () che ha lo stesso nome di get_line () nel file XDR. Potete anche vedere che le linee dall'inizio del file XDR (le tre righe di commento) sono state copiate sulla sorgente Java generata, senza i caratteri iniziali del %. In questo modo Jrpcgen genera commenti che possono essere utilizzati dallo strumento di documentazione javadoc automatico. nbsp; Come tutte le classi principali client-stub, la classe estende JRPCClient. Questa classe fornisce la struttura per server chiamanti RPC utilizzando i protocolli più diversi possibili. Simili alla rilegatura C di ONC RPC, le costanti sono il numero e la versione delle prestazioni così come un numero ordinale per ogni procedura. Dei tre costruttori il primo (public progetto (InetAddress host, boolean stream ) throws RPCError) è probabilmente il piu' utilizzato. Lo utilizzeremo nella nostra applicazione client. Infine, il metodo get_line_1 () è quello che dobbiamo invocare quando vogliamo interagire con il server. L' estensione _1 deriva dal fatto che questa è la realizzazione della versione 1 di questo programma RPC. .. 1.2.2 I file di definizione delle variabili Analizziamo anche una delle tre classi risultato,il result.java: /**************************************** * Distinct ONC RPC/XDR for Java Example * ****************************************/ import com.distinct.rpc.*; public class result implements XDRType { public int number; public String line; public result next; /** * Encodes an object of class result in compliance to RFC 1832 (XDR). * @param xdrs The XDR output stream. */ public void xdr_encode(XDRStream xdrs) { xdrs.xdr_encode_int(number); xdrs.xdr_encode_string(line); xdrs.xdr_encode_boolean(next != null); if (next != null) next.xdr_encode(xdrs); return; } /** * Decodes an object of class result in compliance to RFC 1832 (XDR). * @param xdrs The XDR input stream. * @exception RPCError When the call fails for any reason. */ public void xdr_decode(XDRStream xdrs) throws RPCError { number = xdrs.xdr_decode_int(); line = xdrs.xdr_decode_string(); next = null; if (xdrs.xdr_decode_boolean()) { next = new result(); next.xdr_decode(xdrs); } return; } }; I commenti che vediamo qui sopra sono generati in automatico.Possiamo vedere in che modo la struct result viene trasformata in una classe java tramite xdr.Grazie ai metodi dell'XDRStream xdr_encode_int.xdr_encode_string e xdr_encode_boolean vengono tradotte le variabili c rispettivamente di tipo int,char * e boolean. La classe è formata da due metodi xdr_encode e xdr_decode che rappresentano le azioni di codifica e decodifica. Da notare la trasformazione della lista result in un'applicazione java ricorsiva.nbsp; 1.2.3 L'applicazione Client Ecco il primo passaggio per collegarsi a un server RPC. Non è importante sapere in che tipo di linguaggio è stato scritto il server per poter creare questi tipi di applicazioni.Grazie all'interfaccia XDR rimane tutto trasparente al programmatore. import java.net.*; public class applicazioneClient { static public void main(String[] args) { progetto client; // richiama il nostro progetto.java creato da JRPCgen request req = new request(); try { client = new progetto( InetAddress.getByName(args[0]), // qui va l'indirizzo o il nome del server true); // viene messo a true se si vuole usare il TCP. A false per l'UDP for (int i = 0; i < 8; i++) { for (int j = i + 1; j < 8; j++) { req.from = i; req.to = j; System.out.println("from " + i + " to " + j); res_list rl = client.get_line_1(req); result res = rl.value; while (res != null) { System.out.println(res.number+":"+res.line); res = res.next; } } client.CloseClient(); } catch (Exception e) { System.out.println(e.getMessage()); } ... } } Esaminiamola in dettaglio: Prima di tutto importiamo java.net.* per prendere l'InetAddress del Server. Non includiamo lo stub perchè consideriamo il tutto come un unico package. Poi creiamo una semplice classe applicazioneClient con uno static main(). il main chiede in input un unica stringa con il nome del Server da specificare. Dichiariamo il nostro "progetto". Sarà progetto a occuparsi della connessione con il Server. Apriamo un Exception Context. Di solito, nel caso di JRPC, il Context è utilizzato per gli IOException e JRPCException. .. Con le System.out.println che ho messo sul codice possiamo stampare il risultato dell'appicazione Client. Ora, possiamo eseguire la connessione con un semplice richiamo del costruttore "progetto". I parametri di ingresso sono il nome del server e un booleano che dice il tipo di protocollo: true per il TCP e false per l'UDP. Se non viene lanciata alcuna Exception allora vuol dire che siamo connessi. Una volta lanciata la connessione, possiamo iniziare a invocare la richiesta e prelevare i risultati. Istanziamo l'oggetto req, invochiamo il Server con res_list rl = client.get_line_1(req); e preleviamo i dati con l'oggetto res. Alla fine liberiamo la memoria e chiudiamo la connessione con client.CloseClient();. Se la compilazione è andata a buon fine il risultato dell'appicazione sarà questo: >java progetto localhost from 0 to 1 0:prima riga di testo from 0 to 2 0:prima riga di testo 1:seconda riga di testo from 0 to 3 0:prima riga di testo 1:seconda riga di testo 2:terza riga di testo from 0 to 4 0:prima riga di testo 1:seconda riga di testo 2:terza riga di testo 3:quarta riga di testo from 0 to 5 .... Se invece compare questo: >java progetto localhost Server not available. vuol dire che il server non è attivo. 1.2.4 Applicazione Client con le Applets In linea di massima, potete utilizzare l'ONC RPC/XDR per classi e stubs Java generati da Jrpcgen dentro un applet come descritto sopra. Ma osservate che per default tutti i browsers Java-enabled non permettono collegamenti di rete a hosts diversi da quelli da dove viene caricata l'applet. Per poterlo fare , magari per la necessità di accedere alle risorse del client oppure per collegarsi a sua volta su un database situato in un altro pc, bisogna prendere degli accorgimenti. Le soluzioni sono due: o si fa uso di certificati digitali, e da cio' parte un discorso molto vasto per via della diversità dei vari browsers, oppure configurando il JRPCgen nel classpath del browser della macchina che apre la connessione RPC. Se entrambi i metodi non sono attuabili per la vostra applicazione oppure dovete collegarvi a un server RPC che è protetto da un firewall ,è possibile utilizzare sempre il protocollo HTTP utilizzando dei canali particolari.I particolari li vedremo nella seconda parte del tutorial. Con questa caratteristica univoca dell'ONC RPC/XDR si possono utilizzare facilmente piu' server in cascata. Pero' ci potrebbbero essere cali di prestazioni rispetto al collegamento diretto descritto prima ..
|