M. Barbaro, G. Rorato Client/Server 6 WEB Il grande successo del progetto World Wibe Web, ideato da Tim BernersLee al CERN di Ginevra nel 1989, si basa fondamentalmente sulla possibilità di collegare tra loro una grande quantità di ipertesti, termine usato per primo da Ted Nelson nel 1965, che voleva realizzare una raccolta globale di testi e di ciò parlava nel suo progetto Xanadu di cui si possono trovare informazioni più dettagliate all'indirizzo http://xanadu.net/the.project. Ciò che si voleva garantire era comunque un modo per poter avere una consultazione testi non più sequenziale ma a grafo, di testi situati su macchine anche molto distanti tra loro attraverso l’utilizzo delle reti telefoniche. Dall’ipertesto al WEB Internet è una rete eterogenea di calcolatori dislocati in tutte le parti del mondo che si basa sul protocollo di trasmissione TCP/IP; a livello più alto rispetto a questo protocollo risiede il protocollo HTTP che consente lo scambio di ipertesti. Comunque il modello di iterazione tipico della rete è quello classico client-server dove un server HTTP è un programma che gira su di una macchina in attesa di richieste dai clienti HTTP detti anche browser. Sollecitato dal browser, il server risponde inviando un documento redatto in HTML, che è il linguaggio usato per scrivere i documenti che appaiono sul Web. Un tipico esempio di applicazione Web può essere formato da una pagina HTML statica, memorizzata cioè su di un file, che permette al suo interno ad un’utente di richiamare ad esempio 109 M. Barbaro, G. Rorato Client/Server un programma CGI; quest’ultimo, una volta attivato, genera dinamicamente una pagina che contiene tutte le informazioni richieste dall’utente. Tutti questi concetti appena introdotti verranno comunque spiegati successivamente nei prossimi paragrafi del capitolo. L'HTML Verrà ora analizzato brevemente il linguaggio HTML; sebbene semplice, questo linguaggio sottoinsieme di SGML (che è un linguaggio utilizzato per indicare la semantica di un testo) è un cosiddetto Markup Language, ovvero un linguaggio di istruzioni composto di elementi che definiscono le caratteristiche di un documento e ne guidano la scomposizione sullo schermo. Sua peculiarità è di descrivere i contenuti invece delle apparenze: non rigide misure di formattazione, ma semplici etichette o tag che identificano la funzione degli elementi che compongono il testo, in contrasto invece con lo stile WYSIWYG, cioè “What you see is what you get”. Esempio di documento HTML <HTML> <HEAD> <TITLE>Titolo</TITLE> </HEAD> <BODY> Applicazioni client/server </BODY> </HTML> Sarà il browser, e quindi in una certa misura l’utente, a decidere esplicitamente come le singole parti del documento si presenteranno sulla pagina. Da notare che non tutti i browser esistenti (Netscape, Internet Explorer, ecc.) leggono un testo allo stesso modo, quindi di certe formattazioni vanno considerati anche gli effetti su browser come, per esempio, Lynx che non è in grado di visualizzare le immagini ma solo testi. URL Un URL (Uniform Resource Locator) è un qualsiasi tipo di indirizzo, o “arco”/anchor secondo la rappresentazione Web=(N,E) dove N sono i nodi e E appunto gli archi, Internet, sia esso un recapito di posta elettronica o il riferimento necessario per raggiungere una pagina Web, un sito gopher o FTP o un’area Usenet. Un URL si compone di diverse parti, divise tra loro da un separatore (/), ognuna delle quali è portatrice di una parte delle informazioni necessarie all’utente. Ecco uno schema: protocollo:[//]host[:porta][path] La prima parte di un URL sarà quindi del tipo: - http (può comunque simulare gli altri protocolli). 110 M. Barbaro, G. Rorato - Client/Server ftp, un protocollo per il trasferimento di file. telnet, un protocollo per permettere a un utente il collegamento remoto a un computer. gopher, news (protocolli che non verranno analizzati in queste dispense). La seconda parte di un URL indica il nome del server a cui ci si collega, mentre la quarta indica invece la collocazione all’interno del server della pagina a cui si vuole accedere. In “mezzo” sta il numero di porta su cui è aperta la connessione del server che, per esempio per http, è in attesa di default sulla porta 80. In questo modo quindi un client instaura una connessione di tipo socket sulla porta 80 o su quella indicata nell’URL indicando (lo fa automaticamente il browser) nella richiesta al server un metodo, (ad es. GET) indirizzo e protocollo. Se la connessione invece è di tipo telnet questi parametri vanno esplicitamente indicati dall’utente. HTTP L’HyperText Transfer Protocol (HTTP) è un protocollo che si “appoggia” al protocollo di trasmissione TCP/IP ed è usato dai client (browser) nel Web per comunicare con i server WWW. L’hypertext transfer protocol HTTP è un protocollo abbastanza semplice che permette la trasmissione di dati in formato ASCII a 7 bit. Un client instaura una connessione su un socket verso un server HTTP che attende di default sulla porta 80 o comunque su di una porta indicabile nell'URL. A questo punto il client fa una richiesta indicando metodo, indirizzo e protocollo. Un tipico esempio di richiesta è il seguente: GET address HTTP /1.0 Nella linea precedente si è introdotto uno dei metodi usati maggiormente per introdurre delle richieste, cioè GET; in alternativa si sarebbe potuto utilizzare, ad esempio, il metodo POST che prevede anche alcuni header opzionali di richiesta, una linea vuota e in alcuni casi dopo quest'ultima sono compresi dei dati per il programma server. A questo punto il server HTTP spedisce una risposta contenente una linea di stato cioè un codice numerico indicante o meno un successo, alcuni header di risposta, una linea vuota, il documento richiesto e poi chiude la connessione. Da notare che queste richieste sono effettuate automaticamente da un browser, mentre se si instaura una connessione di tipo telnet si deve indicare esplicitamente la riga di richiesta, gli header, ecc. La richiesta 111 M. Barbaro, G. Rorato Client/Server Rivedendo quanto detto nel paragrafo precedente verranno successivamente introdotti alcuni dei metodi possibili per fare una richiesta e alcuni header opzionali usati per indicare ulteriori informazioni che è possibile fornire al server. I metodi Ecco i metodi principali con cui si può formulare una richiesta: GET è il più usato dai browser per richiedere normalmente un documento; dei dati da fornire ad un programma CGI possono essere indicati dopo un carattere di questo tipo: "?". HEAD è identico a GET ma il server si limita a ritornare solo gli header di risposta. POST permette invece di indicare dei dati per un programma CGI su di una linea apposita dopo la linea vuota. Il programma CGI può usare l'header Content-Length per determinare quanti dati deve leggere. PUT, poco supportato finora, permette ad un client di chiedere ad un server di memorizzare un documento. Gli header di richiesta Ecco una descrizione di alcuni tipi di header che un client può indicare nella richiesta come intestazione: Accept specifica il tipo di formati MIME, riguardanti per esempio lo standard delle immagini, dei file audio, ecc., che il client desidera supportare. Più opzioni possono essere indicate semplicemente separandole con un “;” Connection:Keep-Alive; il protocollo HTTP 1.0 è stateless, cioè senza stato poiché crea una nuova connessione per ogni documento che viene richiesto dallo stesso client senza tenere traccia di un eventuale connessione precedente. Con questo header si vuole ovviare a questa mancanza permettendo di mantenere attiva la connessione. Content-Length è di solito aggiunto alle risposte di un server ma deve essere supportato nelle richieste di tipo POST. Cookie:namel=valuel;...;nameN=valueN; i cookie permettono di memorizzare delle informazioni utili al server per riconoscere il tipo di client nel client stesso. User-Agent specifica il tipo di browser dell'utente. I venditori possono scegliere il formato per riempire questo header; in particolare il più comune è Mozilla che viene usato per indicare Internet Explorer e Netscape. Il formato è comunque spesso simile a: Esempio: Accept: */* indica che il client accetterà di tutto. Vendor/version (platform; encryption; os) 112 M. Barbaro, G. Rorato Client/Server La risposta Dopo aver ricevuto una richiesta valida il server restituisce una linea di stato indicante un codice numerico. In particolare si ha che: un valore compreso tra 200 e 299 indica successo. un valore compreso tra 300 e 399 indica che il file richiesto è stato spostato. un valore compreso tra 400 e 499 indica un errore del client. un valore compreso tra 500 e 599 indica un errore del server.. Esistono solo alcuni codici predefiniti ma se il browser riconosce un codice sconosciuto può usare i range indicati per decidere quali azioni intraprendere. Dopo la linea di stato possono essere inclusi, analogamente a quanto visto nella richiesta, degli header perlopiù opzionali; in particolare l'header Content-Type, che indica il tipo MIME e il sottotipo dell'entità che il server sta inviando, dovrebbe essere sempre indicato in modo che il browser sappia sempre che cosa fare con il documento che gli viene recapitato. Cookie: memorizzare dati persistenti su di un client Netscape, Internet Explorer e altri browser forniscono un meccanismo che permette di memorizzare semplici informazioni sulla macchina del client. A seconda di quali parametri sono memorizzati il browser può includere questi dati in future richieste allo stesso server e che comunque non verranno spediti ad altri domini. I Cookie permettono ad un sito di memorizzare alcune preferenze di un utente, di supportare uno user-id e/o una password tali che l’utente non li debba riscrivere in successive sessioni, di tenere traccia di acquisti, di tenere traccia delle attività di un utente finché visita un certo sito, ecc. La sintassi di un cookie Il server chiede ad un client di memorizzare un cookie tramite l’header Set-Cookie; si possono avere fino a 20 cookie per sito specificando più righe per ognuno di questi. Un browser può rispedire ad un server un cookie creato in precedenza tramite l’header Cookie e inoltre più cookie possono essere specificati separandoli con “;” lungo una singola linea Cookie. Esempio: Set-Cookie: cookieName=cookieValue /*Sintassi*/ /* Nelle prossime due righe ricerca che possa permettere termine ricercato dovrebbero conciso o esteso, tramite cui si suppone di avere a che fare con un motore di agli utenti di decidere quante occorrenze di un essere riportate e di poter decidere il formato, visualizzare queste occorrenze */ 113 M. Barbaro, G. Rorato Client/Server Set-Cookie: hits-per-page=10 Set-Cookie: format=verbose /* Per il resto seguente: */ della sessione un browser spedirebbe una linea del tipo Cookie: hits-per-page=10; format=verbose Opzioni di un cookie expires è un attributo che specifica per quanto tempo un cookie può essere considerato valido. Se non è supportato il cookie sarà valido solo durante la sessione corrente. Un cookie può essere cancellato indicando una data "vecchia". Esempio: Set-Cookie: hits-per-page=10; expires=Friday, 01-Jan-1999 00:00:00 GMT path indica una serie di URL che dovrebbero ricevere il cookie dal browser. “/” indica il path più generale. domain indica la possibilità a più siti di condividere gli stessi cookie. Se viene appunto specificato tutti i siti nel dominio specificato riceveranno il cookie. Esempio: Set-Cookie: hits-per-page=10; expires=Friday, 01-Jan-1999 00:00:00 GMT path=/ domain=.search-service.com Problemi di sicurezza Molti utenti sono preoccupati per i rischi sulla sicurezza e la privatezza associati con i cookie. C’è comunque da dire che un dato cookie non è mai eseguito in alcun modo dalla macchina del client e così non potrà mai creare virus o programmi distruttivi. Oltretutto a causa della massima dimensione di un cookie (4K) e al fatto che ogni sito ha un limite di 20 cookie, questi non possono neppure essere usati per riempire l’hard disk di un utente. Il problema semmai è per i siti che memorizzano password o altre informazioni di sicurezza introducendo il rischio che questi file possano essere compromessi, specialmente perché molti utenti non sanno che un file cookie dovrebbe essere protetto. Inoltre molti sono perplessi a causa del fatto che un sito che usa cookie può tenere traccia delle pagine che un utente visita, degli argomenti più usati nei motori di ricerca, ecc. accumulando un profilo dell’utente. Per finire un sito non impedisce a siti cooperanti di condividere cookie tra i vari domini. La chiave per risolvere questi problemi risiede nella crittografia. 114 M. Barbaro, G. Rorato Client/Server CGI Il Common Gateway Interface è un metodo che permette alle pagine Web di interagire con Database o programmi che risiedono su di un server HTTP. In particolare esso è usato per tre ragioni principali: 1. 2. 3. Non è sempre desiderabile o opportuno fare girare dei processi (magari pensati per macchine più potenti come le workstation) sulle macchine dei client. Anche se oggi è difficile da pensare, non tutti sono in grado di utilizzare un browser Java. Molti servizi Web esistenti sono da tempo organizzati con interfacce CGI ed è utile sapere come è possibile comunicare con queste pagine Web. In questo paragrafo verranno illustrate le caratteristiche principali di questa tecnica senza comunque addentrarci nelle peculiarità della programmazione CGI. Common Gateway Interface Si può attivare un programma CGI indicando in una richiesta HTTP come GET o POST, un apposito URL, cioè un indirizzo che indica il path (cammino), attraverso varie directory, riservato dal server HTTP all'interno del suo dominio per i propri programmi CGI; di solito queste directory speciali sono del tipo “cgi-bin”, “cgi” o “bin” e al loro interno risiedono appunto i programmi CGI. Se ad un server viene indicato di attivare un programma CGI esso non restituirà come di consueto un documento ma manderà in esecuzione il programma, passandogli i parametri forniti dal client, per poi restituire al client l'output del programma stesso . È inoltre possibile fornire dei dati ad un programma CGI sia “appendendoli” alla fine dell’URL, usando il metodo GET di HTTP, che scrivendoli su di una linea separata usando invece POST di HTTP. Come usare le FORM HTML Uno dei modi per permettere l'interazione e lo scambio dei dati tra client e server è utilizzare le cosiddette FORM o maschere di HTML; infatti tramite questo tag di HTML è possibile definire dei campi all’interno dei quali un utente può accedere e definire alcuni tipi di dati. Questi dati sono spediti ad un programma CGI quando l’utente inizia certe azioni, come “cliccare” su di un bottone di tipo “submit” o su di una immagine di tipo “mappa”. Una volta spedito il dato il programma CGI genera una nuova pagina HTML aggiungendo i risultati e restituendoli al client in modo che questi li possa visualizzare. In alternativa è sempre possibile usare le applet Java per ottenere dell’input da spedire ai programmi CGI. Usando il tag FORM di HTML è possibile specificare l’URL del programma CGI, è possibile denominare ogni elemento di input (con il tag NAME) e, ad alcuni elementi, è possibile aggiungere 115 M. Barbaro, G. Rorato Client/Server un valore iniziale (grazie al tag VALUE) sia assegnando un valore di default che lasciando all’autore della pagina il compito di definire tale valore. Inoltre all’utente è permesso aggiungere dei valori in alcuni specifici textfield, ovvero degli spazi riservati proprio per garantire una certa interattività. Quando un utente clicca su di un bottone di tipo “submit” o su di una immagine-mappa gli elementi attivi sono accumulati in una stringa di tipo “name1=val&name2=val2&...&nameN=valN” che è poi trasmessa all’URL specificato facendo partire un comando che è di tipo GET o di tipo POST. I dati possono essere trasmessi dal client tramite le variabili di sistema o QUERY_STRING sia appendendoli all’URL dopo un carattere del tipo “?” che spedendoli in una linea separata. Il primo metodo permette ad un progettista CGI di fare un facile debug mentre allo stesso tempo però è possibile spedire solo pochi dati con il rischio che oltretutto questi siano visibili all'esterno. Per Esempio, con GET da Telnet è possibile digitare: GET .../bin/search?p=valore&q=value il CGI potrebbe restituire html search (char *p, char *q) Esempio con POST: POST /cgi-bin/search2 [ [ [p=valore&q=value...] L'ultima riga del listato rappresenta i dati da passare in input al programma CGI e che tutti i programmi CGI devono poter leggere (ad esempio PERL, JAVA stesso, ovvero linguaggi di tipo VhLL anche detti ad altissimo livello), di search2. Da notare infine che la QUERY_STRING non può essere gestita da comandi Java per questioni di portabilità in quanto un applet non deve dipendere da variabili di sistema; per ovviare a questo problema si può abbandonare il metodo GET in favore del metodo POST oppure si può incapsulare la QUERY_STRING tramite uno script come nel seguente esempio: #!/bin/sh java applicazione 'QUERY_STRING' Il tag FORM di HTML Le form HTML permettono di creare un insieme di dati da passare in input associati con un particolare URL; ad ognuno di questi elementi è possibile assegnare un nome ed un valore. Ecco come appare il tag FORM in una pagina HTML: <FORM ACTION=”URL” ...> ... </FORM> Attributi: ACTION, METHOD, ENCTYPE, TARGET (non standard), NAME (non standard), ONSUBMIT (non standard), ONRESET (non standard) 116 M. Barbaro, G. Rorato Client/Server Segue un esempio di modulo form tramite cui assegnare dei valori (in questo caso un nome e un cognome) e poi passarli ad un programma CGI definito all'interno della directory /cgi-bon/ dopo la pressione del campo submit: Pagina HTML del server: form(maschera, modulo) <FORM ACTION=”/cgi-bin/...” METHOD=GET...> nome <INPUT TYPE=”TEXT” NAME=”nome” VALUE=” “> cognome <.....> <INPUT TYPE=”SUBMIT” NAME=”Submit”> </FORM> Se invece si volesse realizzare lo stesso passaggio di parametri tramite i metodi GET e POST di HTTP, ecco come si potrebbe fare: GET url/action? cognome= & nome= oppure POST [ content-length:n [ cognome= &nome= dove “n” indica il numero di caratteri che seguono la linea bianca. Ecco ora riassunte le funzionalità di due dei vari attributi: ACTION specifica l’URL del programma CGI che processerà i dati della FORM. METHOD specifica il modo in cui dati verranno trasmessi al server HTTP; sono stati già analizzati i vantaggi e gli svantaggi di GET mentre di POST si può dire che non vi è un limite al numero di dati che possono essere spediti. Approcci alternativi al CGI Un tradizionale processo CGI è relativamente costoso da usare in termini computazionali perché richiede un bel po' di overhead far partire un nuovo programma per ogni richiesta. Sono così stati pensati un gran numero di approcci simili al CGI per evitare questo problema; questi approcci prevedono di poter utilizzare dal lato del server Java o JavaScript, delle API per poter dialogare con le librerie condivise, DLL, o Database che girino contemporaneamente al server HTTP. Ecco quindi una descrizione di due tipi di soluzioni adottate in alternativa a CGI: ISAPI (Information Server API) sviluppate da Microsoft permettono alle DLL, dei programmi in-process, di usare tutte le variabili utilizzate dal server stesso. Sono ormai supportate da molti server Windows 95 e Windows NT e permettono di indicare al server che cosa fare in caso che esso riceva determinate richieste. L'Internet Information Server supporta anche le Active Server Pages (ASP) che invece permettono al server di generare delle pagine HTML dinamiche che estendono e ricreano la pagina originale; 117 M. Barbaro, G. Rorato Client/Server tutto ciò è possibile perché esse contengono al loro interno degli oggetti che possono intervenire sulle pagine tramite degli script. Quest'ultima, comunque, è un’architettura Microsoft non portabile. NSAPI di Netscape sono delle API che permettono a delle libreria condivise (Unix) o a delle DLL di essere integrate nel server. L’object web: CORBA incontra Java Per molti aspetti il corrente paradigma HTTP/CGI, si sta ormai incrinando e le varie estensioni al CGI come cookie, ISAPI, NSAPI e ASP sono visti solo come dei “cerotti” per coprire il problema. Sorge così il bisogno per la rete (il Web) di fare un passo avanti verso l’uso di oggetti distribuiti; questo progetto prende il nome di Object Web. Per risolvere il problema si sta assistendo ad una sorta di “matrimonio” tra CORBA e Java, fatto a cui stanno aderendo tutti i venditori tranne la Microsoft che continua la sua strada con ActiveX/DCOM ed il “suo” Object Web. In questo capitolo tratteremo in breve questo sodalizio, illustrando quali vantaggi esso può portare e cercando di capire i perché dei suoi vantaggi a discapito di CGI. Il nuovo sodalizio Nel giugno del 1997 sorge l’idea, grazie all’Enterprise Server 3.0, della cosiddetta rete oggetto o Object Web, cioè di unire JavaSoft a CORBA e di fornire questi cambiamenti all’interno del nuovo pacchetto JDK V1.2. Questa unione sorge perché questi due linguaggi sembrano complementarsi in un modo molto naturale, tanto che si può dire che Java inizia dove CORBA finisce: CORBA tratta la trasparenza nella rete mentre Java si preoccupa della trasparenza nelle implementazioni. CORBA interviene per estendere le capacità delle applicazioni Java attraverso le reti, diversi linguaggi, diverse componenti, ecc. CORBA aggiunge un insieme di servizi distribuiti come ricerche dinamiche e distribuite, autenticazione, sicurezza, ecc. CORBA, grazie alla sua rappresentazione degli oggetti, non fa trapelare nulla sulla loro relativa implementazione. D’altro canto Java è un linguaggio con codice portabile che fornisce un modo nuovo, più semplice per sviluppare, gestire e distribuire applicazioni client/server. Infatti è possibile distribuire in modo immediato un’applicazione a milioni di client semplicemente ponendola su di un server Web; 118 M. Barbaro, G. Rorato Client/Server inoltre Java è utile anche per i server in quanto permette di spostare dinamicamente i servizi a seconda di dove sono più richiesti. In questo modo Java diventa il linguaggio ideale per scrivere gli oggetti CORBA di un programma server e di un client (ad esempio ora un applet può invocare altre applicazioni presenti nel server) tutto grazie anche al suo multithreading, la sua garbage collection e la gestione degli errori che permettono di scrivere oggetti distribuiti più “robusti”. Alla fine di queste considerazioni possiamo dire che CORBA aggiunge l’anello mancante tra il sistema di applicazioni portabili di Java e il sistema di oggetti nella rete. Uno degli unici svantaggi di questo connubio, almeno a prima vista, è che per far girare questo sistema occorrono due virtual machine, come si può vedere nello schema della figura seguente (Figura 46): Figura 46 Il sistema che occorre per utilizzare Java e CORBA assieme. Conflitti e loro risoluzioni A dire il vero in questo “matrimonio” ci sono state delle incomprensioni dovute al fatto che Java e CORBA in certi aspetti si sono accavallate e intromesse una nel lavoro dell’altra come per esempio quando Java ha definito il suo RMI per comunicazioni da Java a Java attraverso virtual machine. Alla fine comunque, risolti i conflitti, Java ha adottato CORBA come il suo modello per oggetti distribuiti e farà girare le API RMI sull’ IIOP di CORBA. Più precisamente ma senza andare nel particolare, JavaSoft intende includere CORBA nel core di Java ad esempio ponendo un particolare ORB CORBA/IIOP nel core di JDK 1.2 e implementando l’RMI di Java sull'IIOP di CORBA. Come diventa un'interazione client-server con l'object web Ecco i passi principali che percorre un tipico client Web per interagire con il suo server tramite l'Object Web: 119 M. Barbaro, G. Rorato 1. 2. 3. 4. 5. Client/Server Il browser Web scarica la pagina HTML. Il browser Web rintraccia l’applet Java dal server HTTP. Il browser Web carica l’applet. L’applet invoca gli oggetti CORBA del server; poiché per questa operazione occorre un firewall, è possibile, ad esempio, utilizzare il Borland Gatekeeper Visigenic che è basato sulla tecnologia MIDAS. La prossima pagina viene generata dinamicamente. Il tutto può essere riassunto tramite l'immagine presente nello schema seguente (Figura 47): Figura 47 I vari passi che rappresentano l'interazione tra un client e un server all'interno dell'oggetto rete.. Gli svantaggi delle altre soluzioni I motivi dell'introduzione della rete oggetto risiedono nel fatto che HTTP con CGI è un protocollo lento, senza stato e inadatto a scrivere applicazioni client/server moderne; con CGI, ad esempio, bisogna far partire una nuova istanza di un programma ogni qualvolta un applet invoca un metodo, cosa che con CORBA non accadrebbe. Finora, per risolvere questi problemi, ogni venditore (o quasi) ha adottato la propria soluzione introducendo così nella rete un’altra ondata di estensioni non standard ed in certi casi proprie di solo alcune piattaforme. Esempi di queste soluzioni sono quelle già viste nel paragrafo precedente come le NSAPI di Netscape, le ISAPI di Microsoft, i Web Object di NeXT/Apple, i Servlets di Java, WinCGI e FastCGI. Per evitare inoltre la mancanza di stato di HTTP alcuni di questi venditori hanno introdotti i cooki, già analizzati nel paragrafo precedente, in altri casi, come le ASPs della Microsoft, si estendono questi cookie con oggetti di sessione (invocati a turno da script) sui server che servono a rappresentare i loro client. Il vero problema, non risolto con questi approcci alternativi, è che non esiste un modo diretto che permetta ad un oggetto di un client di invocare un oggetto di un server. 120