COREP Consorzio per la Ricerca e l’Educazione Permanente Master in Tecnologia e Comunicazione Multimediale Il linguaggio Java come supporto ad un’architettura Client/Server Tesi di diploma di: Luca Martini Dicembre 1996-Novembre 1997 Indice Indice .................................................................................................................. 1 Introduzione ....................................................................................................... 2 Primo Capitolo: Internet, TCP/IP, e WWW............................................................. 5 Secondo Capitolo: Architetture Client/Server ........................................................13 Terzo Capitolo: Server Web, Java, CGI, ACTIVE X .................................................19 Quarto Capitolo: Conclusioni ...............................................................................23 Appendice A: Sorgente Java ................................................................................26 Appendice B: Il Calcolo della Riscrittura di Termini.................................................43 Bibliografia ........................................................................................................48 1 Introduzione L’enorme successo di Internet, al di là degli evidenti vantaggi di aver dato accesso ad immense quantità di informazioni tramite il più noto dei suoi servizi, ovvero il World Wide Web, ha aperto anche nuove prospettive e possibilità per le aziende, sia per quanto riguarda il business on line (promozione e commercio elettronico), sia per l’organizzazione gestionale e operativa interna all’azienda stessa. Proprio su questa seconda opportunità vogliamo porre l’attenzione, perchè riteniamo che l’utilizzo della tecnologia Internet internamente all’azienda, ovvero INTRANET, offra effettivi vantaggi e interessanti servizi a fronte di investimenti modesti. Una rete INTRANET altro non è che una rete di computer locale che utilizza lo stesso protocollo di comunicazione di Internet (TCP-IP), e sostanzialmente gli usuali strumenti di navigazione (browser quali Netscape, o Internet Explorer), che hanno, come è noto, molti vantaggi: sono universali (ovvero girano su qualsiasi piattaforma, Windows, Apple, Unix, ecc...); sono a costo zero o soggetti a una royality modestissima; sono facilmente utilizzabili e largamente conosciuti dall’utente. Una rete INTRANET può contribuire a realizzare un efficiente sistema informativo andando ad intergrarsi con quelli esistenti all’interno dell’azienda e con le applicazioni utilizzate. Ma quali sono effettivamente i vantaggi di una INTRANET ? I principali benefici, anche per aziende di piccole dimensioni, sono rappresentati 2 dalla possibilità di distribuire con facilità dati ed applicazioni sulla rete locale: rapporti, listini, cataloghi, anagrafiche, posta interna, manuali, applicazioni office, movimenti contabili, moduli di ordine che vanno ad intervenire sugli archivi esistenti, ecc... Il tutto utilizzando lo stesso strumento di lavoro (il browser per l’appunto). Inoltre l’investimento per realizzare una INTRANET è particolarmente ridotto perchè la parte Client (ovvero le stazioni di lavoro) è interamente gestita dal browser e può indifferentemente girare su qualsiasi tipo di calcolatore o sistema operativo. Infine un ulteriore vantaggio è rappresentato dalla possibilità di esportare, anche successivamente, su Internet una o più applicazioni esistenti, aprendo quindi una finestra di propria attività sulla rete mondiale (cataloghi, listini, commercio elettronico, ecc...). Analizziamo in breve il contenuto dei singoli Capitoli: Capitolo primo: Internet, TCP/IP, e WWW. In questo Capitolo, introduciamo Internet, tracciandone la storia e lo sviluppo, e descrivendo il suo protocollo di comunicazione (TCP/IP) e il più noto dei suoi servizi (WWW). Capitolo secondo: Architetture Client/Server. Con questo capitolo vogliamo introdurre il modello Client/Server, confrontandolo con quello tradizionale a mainframe. Capitolo terzo: Server Web, Java, CGI, ACTIVE X. In questo Capitolo, vengono confrontati i tre metodi software adottati dai più importanti browser per realizzare architetture Client/Server con Internet, e presentate le loro interazione con un Server Web. Capitolo quarto: Conclusioni. 3 In questo Capitolo tracciamo i possibili sviluppi futuri, con particolare attenzione all’area della Programmazione Logica e a quella del Calcolo della Riscrittura di Termini. Appendice A: Sorgente Java. In questa Appendice, riportiamo alcuni sorgenti in codice Java per l’interfacciamento con un database Oracle, e per realizzare una connessione fra Sever e Client per la scrittura sul Server di nuovi file HTML. Appendice B: Il Calcolo della Riscrittura di Termini. In questa Appendice, presentiamo il Calcolo della Riscrittura di Termini in rapporto al modello Client/Server e all'Elaborazione Distribuita. 4 Primo Capitolo Internet, TCP/IP, e WWW Internet Internet è sicuramente un autentico prodigio tecnologico, secondo alcuni il manufatto più sofisticato mai prodotto dall'attività umana, al tempo stesso semplice ed elegante dal punto di vista concettuale e progettuale: il mezzo finale di comunicazione, capace di veicolare, riassumere e assimilare quelli già esistenti e di ricondurre a sè ogni possibile, futura modalità comunicativa. Uno strumento unico per comunicare con il mondo intero, già oggi (tramite una dotazione tecnologica minima e alla portata di tutti) e sempre di più in un domani che vedrà la digitalizzazione di tutte le informazioni. Uno strumento della cui versalità e flessibilità al momento non si scorgono limiti. Come e forse più che negli anni '80, quando con l'affermarsi del personal computer la tecnologia informatica è entrata in tutte le case e ha rivoluzionato tutti i settori produttivi e la stessa vita quotidiana, Internet è destinata a sconvolgere (come già sta facendo) la nozione stessa di comunicazione, con conseguenze sociali di vasta portata. Ripercorriamone brevemente la storia. Nel 1969 diviene operativa una prima versione di un progetto militare statunitense commissionato dal Dipartimento della Difesa all’agenzia governativa ARPA (Advanced Research Projects Agency). Lo scopo del progetto è la creazione 5 di una struttura informativa che permetta lo scambio di dati tra i vari organi della difesa nazionale e il cui funzionamento non dipenda da nessuno dei suoi singoli nodi, contrariamente alle reti di comunicazione tradizionali, come quella telefonica o telegrafica: in caso di avaria (o di attacco nemico) a un nodo della rete, le comunicazioni devono essere possibili tra tutti i centri ancora opertivi. Un ulteriore elemento di affidabilità sarebbe stato introdotto dal supporto del collegamento, non più unicamente su linea dedicata ma su normali linee telefoniche. Gli scambi di informazioni, infatti, avvenivano secondo la tecnica del Circuit Switching (Commutazione di Circuito), in genere implementata collegando ciascun computer a linee dedicate, al di fuori degli standard elettronici e telefonici commerciali e spesso costosissime. L'adozione della linea telefonica, su cui viaggiano contemporaneamente numerosi segnali, ciascuno relativo a comunicazioni diverse, porta alla scelta e allo sviluppo definitivo di una nuova tecnica di trasmissione di dati detta Packet Switching (Commutazione a Pacchetto). Nella Commutazione a Pacchetto i dati da trasmettere vengono organizzati in moduli indipendenti (i pacchetti), ciascuno dei quali porta con sè l'indirizzo del mittente, quello del destinatario, e l'ordine di trasmissione, in modo da consentire alla macchina ricevente di ricostruire l'esatta sequenza in cui i pacchetti costituiscono il messaggio. Un approccio innovativo alla trasmissione dei dati, che trasforma la vecchia nozione di rete (molto simile a un circuito ferroviario rigidamente organizzato in binari unici, in cui nessun treno può superare o dare la precedenza a un altro) in una sorta di autostrada con un gran numero di corsie, in cui i messaggi viaggiano indipendentemente gli uni dagli altri. Il successo della nuova rete è immediato: il progetto dell'ARPA viene assorbito dal Defense Advanced Project Research Agency (DARPA) che riprende e aggiorna lo sviluppo dell'originario software di protocollo del controllo di Rete (NCP, 6 Network Control Protocol). Il nuovo nato, che risponde a mutate esigenze di commutazione tra reti eterogenee, si articola nel protocollo di controllo della trasmissione TCP (Transmission Control Protocol) e nel protocollo Internet IP (Internet Protocol). TCP/IP La spinta per lo sviluppo del protocollo TCP/IP venne data dalle nuove esigenze nate dallo sviluppo e dall’integrazione di reti diverse, che si trovavano nella necessità di comunicare: reti via satellite, reti via radio a commutazione di pacchetto e naturalmente ARPAnet. Il lavoro di progettazione e sviluppo di TCP/IP è un primo esempio “metodologia Internet”: molto semplicemente, quando c’è bisogno di qualcosa, la si fa, la si collauda “nel mondo reale” e una volta che è stata ottimizzata la si generalizza, definendo uno standard. I nuovi protocolli vennero utilizzati per ARPAnet a partire dal 1° gennaio 1983, data che per alcuni costituisce la nascita ufficiale di Internet: la maggior affidabilità ed efficienza di TCP/IP rispetto al suo predecessore NCP furono la causa principale della migrazione di tutte le principali Reti a commutazione di pacchetto verso il nuovo protocollo, che si impose in breve come lo standard di riferimento. Il protocollo di controllo della trasmissione (Transmission Control Protocol) è la prima interfaccia software verso la Rete e colloquia principalmente con le applicazioni di livello superiore, quelle a diretto contatto con l’utente. Di concerto col sistema operativo, TCP soddisfa un gran numero di esigenze dei programmi applicativi, che basano i propri protocolli interni su servizi messi a disposizione da TCP: è il caso del protocollo per il trasferimento di file (FTP), del protocollo semplice per il trasporto di posta elettronica (Simple Mail Transfer Protocol, SMTP) 7 o di una sessione di TELNET (simulazione di terminale remoto). Quando avviamo singoli applicativi che implementano queste funzioni (come Eudora, nel caso della posta elettronica), essi si preoccupano in primo luogo di stabilire una comunicazione col software che implementa i protocolli TCP (come Winsock Trumpet o MacTCP) e che da quel momento è disponibile all’applicazione. Tra le funzioni per cui un programma applicativo che ha necessità di colloquiare in Internet può rivolgersi a TCP, vi sono la sua gestione dei dati orientata alla connessione, il trasferimento dei dati, il controllo del flusso di trasmissione e il trasferimento fullduplex (bidirezionale simultaneo). Una caratteristica di TCP che non tutti i programmi sfruttano, ma che è incorporata nella definizione dello standard del protocollo, è quella di specificare livelli di sicurezza e di priorità per la connessione. Questo per quanto riguarda il colloquio fra TCP e lo strato superiore. Lo standard TCP non comprende infatti alcuna specifica per quanto riguarda le comunicazioni con lo strato inferiore, sottointendendo che questo è in grado di scambiare informazioni con TCP in modo asincrono. Il protocollo Internet si occupa di fornire tutti i servizi necessari alla gestione del traffico tra l’utente e la rete sottostante, nonchè (installato sui server di rete e sui gateway) tra le varie sottoreti attraverso cui i dati transitano per arrivare a destinazione. Si tratta di un cosiddetto “protocollo senza connessione” che non prevede alcun controllo sull’integrità e sulla completezza dei dati dalla partenza alla destinazione e che deve perciò appoggiarsi a un protocollo di livello superiore, come appunto TCP. Questo significa anche che IP è un protocollo relativamente semplice e “ignorante”: occupandosi esclusivamente della confezione e dello smistamento dei pacchetti (o “datagrammi”), nonchè del loro instradamento/ricezione, esso possiede ben pochi indizi sul funzionamento della 8 Rete o delle reti sottostanti, il che rende queste ultime relativamente indipendenti da IP stesso. In Internet è fondamentale distinguere chiaramente alcune nozioni che vengono spesso confuse. Un nome è un identificatore alfanumerico (cioè una sequenza di caratteri e cifre) che indica una certa entità, quali un computer, un programma, una persona, una rete, indipendentemente dalla loro dislocazione fisica. Un indirizzo è un altro identificatore che fornisce informazioni di natura molto più approfondita e specifica a proposito di una certa risorsa, quali la sua posizione fisica o logica nella Rete. Un percorso è l’insieme delle informazioni e delle modalità da seguire necessarie al reperimento di una posizione fisica (sia essa un indirizzo o meno). Non è in realtà una distinzione difficile, anche perchè si basa sul modello postale/telefonico che tutti conosciamo e che in effetti costituisce ancor oggi l’idea alla base della maggior parte delle sottoreti che afferiscono a Internet. Nella pratica, l’utente utilizza di solito un nome per identificare il destinatario di una certa comunicazione; un name server (o server di nomi) risale dal nome all’indirizzo del destinatario, indirizzo da cui si ricostruisce il percorso fisico attraverso un protocollo di routing. Si tratta di un’impostazione che consente una grande elasticità nella gestione delle risorse di rete, permettendo a sistemisti e amministratori di sistemi di riconfigurarle e di ottimizzarle senza che ciò tocchi in alcun modo gli utenti finali. Anche se l’utente finale ha a che fare solitamente col nome della risorsa di rete a cui vuole accedere (per esempio, un altro computer di rete), la prima cosa di cui si incarica il name server residente sull’host dell’utente è la sua traduzione in un indirizzo IP, cioè l’indirizzo di rete comprensibile agli strati successivi di software 9 che implementano i protocolli di trasmissione. Le reti TCP/IP implementano indirizzi a 32 bit che codificano la rete di appartenenza della risorsa (indirizzo di rete) e l’host che la supporta (indirizzo di host). La struttura dell’indirizzo IP è quindi: indirizzo IP=indirizzo di rete+indirizzo di host, a cui i 32 bit disponibili possono essere riservati in più modi, secondo la ripartizione seguente: Classe A [rete.host.host.host] 0-Rete (7 bit)-Indirizzo locale (24 bit) Classe B [rete.rete.host.host] 10-Rete (14 bit)-Indirizzo locale (16 bit) Classe C [rete.rete.rete.host] 110-Rete (21 bit)-Indirizzo locale (8 bit) Classe D [non applicabile] 1110-Indirizzo multicast (28 bit)(16 bit) Ricordando che N bit permettono di codificare 2^N numeri, è facile constatare che le diverse classi di indirizzamento riflettono esigenze di bilanciamenti reti/host alquanto diverse. Gli indirizzi di classe A riservano 24 bit all’indirizzamento di rete e 7 all’indirizzamento dell’host. Questo significa che permettono di indirizzare 2^7=128 reti (in realtà 126, perchè i valori 0 e 127 sono riservati) e 2^24=1677216 host (in reltà, 1677124). In formato binario, un indirizzo IP (di classe C, per esempio) avrà un formato del tipo 11000001 11001111 00000010 00011111 dove è stata evidenziata la suddivisione nei 4 byte che lo costituiscono. Di solito i byte vengono rappresentati in forma decimale e separati da un punto. Così, il nostro indirizzo diventa: 193.207.2.31 una forma già molto più familiare ai frequentatori di Internet. In questo formato, 193.207.2 è l’identificatore di rete della risorsa, mentre 31 è l’indirizzo dell’host. WWW 10 La nascita di un mercato Internet diffuso, in cui ciascuno può disporre di una propria connessione, ha portato all’esplosione più che esponenziale della richiesta di gestione e manutenzione dei servizi legati alla Rete. Come avviene sempre in questi casi, a tale richiesta è subito corrisposta anche una tendenza alla semplificazione degli ambienti già esistenti e allo sviluppo di nuovi, maggiormente amichevoli e di rapido apprendimento. Così il tempo e i costi di avviamento di un nodo (hardware, software e risorse umane) hanno subito una diminuizione drastica e continuano a scendere costantemente. Il caso più clamoroso è quello del World Wide Web, la ragnatela mondiale ormai costituita da decine di migliaia di siti in tutto il mondo. Com’è noto, non è solo una delle tecnologie Internet più recenti, sviluppata presso il CERN di Ginevra negli anni 1989/91, ma anche la più diffusa e popolare, e che molti utenti letteralmente identificano con Internet. I motivi sono abbastanza chiari: il protocollo HTTP (Hyper Text Transfer Protocol) su cui si basa WWW, supportato da browser ormai popolarissimi come Mosaic, Netscape Navigator o Microsoft Explorer, consente la trasmissione di dati e informazioni con una ricchezza in precedenza impensabile, realizzando un’effettiva ipertestualità del messaggio. In un unico documento Web convivono testo, immagini, e suoni, in un amalgama assolutamente inedito di dati e informazioni che attraverso la Rete vengono messi a disposizione. La tecnologia Web è nata in anni recenti ed è già “adulta”, nel senso che sia i programmi client che la implementano che gli ambienti di sviluppo (software di installazione e di gestione del server Web, editor HTML, ecc...) fin dall’inizio sono stati sviluppati con interfacce grafiche evolute e “amichevoli”. Questo fatto ha giocato una parte considerevole nell’incredibile risposta che Web ha avuto in tutto 11 il mondo e che ha portato a una successiva, ulteriore diffusione degli strumenti di sviluppo e manutenzione: oggi la realizzazione di un server Web, cioè di una macchina su cui realizzare siti Web, è alla portata sia economica che tecnologica di praticamente chiunque desideri farlo. L'enorme richiesta per questo tipo di installazioni ha infatti portato alla nascita di ambienti di sviluppo sotto piattaforme commerciali (quali Windows e MacOS) togliendo alle workstation Unix il monopolio sulla gestione dei servizi Internet, e in particolare dei siti Web. Un esempio è fornito dall'attenzione della Microsoft per ogni tipo di tecnologia Internet e per quella WWW in particolare, considerata strategica. Il sistema operativo Windows NT, per esempio, era sì nato come possibile alternativa a concorrenti come OS/2 e Unix come sistema per workstation/server di Rete (locale, naturalmente), ma si è definitivamente affermato con la nascita di una vera e propria nuova "figura" di workstation, quella del server Internet. Limitandoci per semplicità al caso in cui si voglia implementare un server Web, oggi una configurazione basata su Windows NT rappresenta una scelta praticabile da chiunque, sia per costi hardware/software che per competenze necessarie: la documentazione tecnica è infatti abbondante e di facile reperibilità. 12 Secondo Capitolo Architetture Client/Server Il modello Client/Server L'elaborazione Client/Server è oggi la tecnologia che sta compiendo i maggiori progressi nel settore dell'informatica: il suo utilizzo è destinato a diffondersi e a ridefinire la modalità di elaborazione e produzione delle applicazioni negli anni Novanta e oltre. Ora che l'evoluzione del mercato dell'informatica punta decisamente in direzione di personal computer potenti ma economici, il momento è propizio perchè l'elaborazione Client/Server possa sbocciare. Sempre più frequentemente, i nuovi PC vengono collegati in rete per formare ambienti interconnessi di rete locali (LAN). Sfruttando appieno la LAN e tutti i suoi componenti elaborativi, la tecnologia Client/Server è diventata un'alternativa possibile all'elaborazione mainframe centralizzata; questo non significa tuttavia che i mainframe siano finiti o sorpassati. L'elaborazione Client/Server fa leva sull'enorme potenziale degli ambienti LAN interconnessi. La possibilità di eseguire un programma in più macchine comporta un potenziale incremento delle prestazioni e della scalibilità. L'elaborazione Client/Server definisce un nuovo metodo di elaborazione, rimettendo in discussione le modalità precedenti di esecuzione e gestione dei programmi. I programmi tradizionali vengono eseguiti in una singola macchina: le 13 applicazioni possono essere mainframe, nel qual caso tutta l'elaborazione viene svolta nel computer mainframe centrale, oppure autonome, nel qual caso tutta l'elaborazione avviene in un personal computer o in una stazione di lavoro. Le applicazioni Client/Server sono diverse, in quanto vengono eseguite sia in un client sia in un server e fondono le parti migliori delle applicazioni autonome e di quelle mainframe in un ambiente coesivo. Più precisamente: Client/Server è la suddivisione di un programma applicativo in due componenti logicamente separati, ciascuno dei quali assolve mansioni molto diverse. In generale, un client invia al server la richiesta di eseguire un lavoro, mentre al server spetta elaborare le richieste del client e restituire i risultati. Questo processo avviene quasi sempre tra due computer fisicamente separati, in qualche tipo di infrastruttura fisica di LAN. Solitamente, gli elaboratori server sono molto più capienti e più veloci e sono quindi idonei per gestire il lavoro proveniente da altri sistemi. La tecnologia client/server è costituita da programmi client, o front-end, che coordinano la logica delle applicazioni con un'applicazione server, o back-end, utilizzando la LAN come mezzo di comunicazione. Questa suddivisione delle applicazioni consente l'elaborazione del lavoro da parte di due computer invece di uno solo. L'evoluzione verso l'informatica distribuita può addirittura determinare il coinvolgimento di molti server nell'elaborazione back-end della logica delle applicazioni. La combinazione di questi sistemi offre enormi possibilità di ottenere applicazioni ad alte prestazioni e un grado elevato di scalabilità. La flessibilità della tecnologia client/server consente di eseguire l'elaborazione nel punto in cui questa risulta più efficiente. Molti sono i vantaggi offerti dalla possibilità di ospitare i componenti logici delle applicazioni nel client o nel server: 14 grazie alla migrazione di parti del programma applicativo tra il client e il server, lo sviluppatore può determinare il conseguimento di risultati ottimali. In alcuni prodotti di sviluppo client/server, la posizione dell'esecuzione può addirittura essere una decisione run-time. Poichè l'elaborazione può essere situata in qualsiasi punto di una rete, la tecnologia client/server offre la possibilità di scalare in modo efficiente. Per ottenere il giusto equilibrio di client e server, un componente di un’applicazione dovrebbe essere eseguito in un server solo quando l'elaborazione centrale del lavoro costituisce la procedura più efficiente; per esempio, la collocazione di parti di un'applicazione in un server in cui risiedono alcuni dati centrali è un'ottima scelta: i requisiti della rete potrebbero infatti essere meno rigidi perchè la logica dell'applicazione che interfaccia con i dati centrali sarebbe situata sulla macchina con i dati e pertanto questi ultimi non verrebbero trasmessi attraverso la LAN. L'elaborazione client/server è molto diversa dall'elaborazione mainframe. Dal punto di vista della logica, vi sono molte differenze, ma anche alcune caratteristiche simili: entrambe elaborano centralmente la logica delle applicazioni per conto di utenti remoti; inoltre, questi ultimi sono solitamente connessi mediante una qualche forma di rete fisica. Dal punto di vista dell'architettura, la differenza più rilevante tra l'impostazione client/server e l'impostazione centralizzata mainframe è la seguente: con l'elaborazione client/server, i client sono intelligenti, in quanto possiedono una vera e propria CPU e sono in grado di elaborare dati reali, mentre i terminali mainframe di norma fungono semplicemente da input/output di un computer mainframe che elabora centralmente la logica delle applicazioni. I limiti insiti nell'impostazione centralizzata mainframe hanno indotto molte aziende a considerare il downsizing 15 delle loro applicazioni e il passaggio a un ambiente client/server. E' tuttavia importante notare che, con l'aumento della quantità di lavoro del server, il sistema tende ad avvicinarsi all'impostazione mainframe: poichè la tecnologia è solitamente realizzata su macchine di piccole dimensioni, le prestazioni delle applicazioni possono di fatto subire un peggioramento in caso di utilizzo eccessivo del server o di vincolo delle sue risorse. E' essenziale bilanciare il carico di lavoro del server e prevedere alcuni strumenti di scalabilità per consentire il passaggio a sistemi di dimensioni maggiori. La tendenza ad adottare l'elaborazione client/server è storica: innanzitutto, i sistemi operativi sono stati suddivisi in vari componenti e la loro interazione è stata gestita come una serie di processi client e server eseguiti sulla stessa macchina; successivamente, sono stati introdotti file system di rete e la risposta alle richieste di dati o file è stata affidata a una macchina remota: in tali ambienti, le richieste di dati venivano instradate attraverso la rete e gestite da un file server di rete. I software di rete per file server centralizzati, quali Novell NetWare, si avvalgono della tecnologia client/server da oltre un decennio: questi sistemi hanno avuto una notevole diffusione negli anni Ottanta, con l'avvento e il rapido sviluppo delle LAN. In tempi più recenti, molte applicazioni sono state realizzate come tecnologia client/server. Quest'ultima non consiste solo semplicemente nei componenti del sistema che assolvono mansioni quali la condivisione dei file, ma nel vero e proprio spazio delle applicazioni che diventa client/server; di fatto, l'applicazione client/server attualmente più diffusa è il database relazionale: quasi tutti i produttori di database hanno una versione client/server del loro prodotto. Con tali prodotti, le query (interrogazioni) generali (di norma SQL) vengono effettuate nei confronti dei database server: le richieste sono formulate nel client e trasmesse al server 16 per l'esecuzione; il server elabora le query confrontandole con il database memorizzato localmente, quindi restituisce i risultati al client attraverso la rete. Il sistema di gestione dei database si occupa dell'interazione dei componenti client e server. La tendenza in atto nella tecnologia client/server è la distribuzione della logica delle applicazioni: è stato dimostrato che l'elaborazione client/server offre un sensibile miglioramento delle prestazioni per quanto riguarda la gestione delle richieste di file e database. Attualmente la maggior parte dei sistemi operativi è in grado di eseguire l'elaborazione client/server. Come l'elaborazione client/server, l'elaborazione distribuita comporta la distribuzione del lavoro tra più macchine; è tuttavia più ampia, in quanto molte macchine possono elaborare il lavoro per conto degli apparecchi client. L'elaborazione distribuita può essere considerata come un'elaborazione client/server con un solo client e molti server. Nel caso dell'elaborazione distribuita il termine server indica semplicemente un programma che risponde alle richieste e fornisce il risultato dei calcoli a un'unità client richiedente. Il VDR La gestione organica della documentazione di commessa assume molta importanza all’interno dell’azienda, in quanto permette il controllo dei vari processi di progettazione tecnica, approvvigionamento, costruzione e montaggio (questi ultimi legati alla disponibilità di disegni e specifiche tecniche). Attualmente tale gestione è effettuata attraverso l’utilizzo di più procedure informatiche tra loro scollegate e con basi dati diverse; ciò non permette una visione globale delle attività di progettazione nè dello stato di avanzamento dei diversi documenti. 17 Utilizzando una Intranet, cioè una rete locale basata sul protocollo TCP/IP di Internet, si vuole definire un sistema per la gestione della Trasmissione/Ricezione della documentazione di commesse, denominato Vendor Document Register: “V.D.R. (Vendor Document Register), Strumento informatizzato di gestione della documentazione di commessa” (la gestione va intesa sia verso l’interno, cioè Uffici Tecnici, sia verso l’esterno, cioè Clienti e Fornitori). Scopo del progetto è la gestione della storia di tutta la documentazione associata ad una determinata commessa, individuando in essa due fasi, una di definizione, fatta una sola volta nella vita di una commessa, ed una di invio, ripetuta più volte. Il progetto è stato sviluppato secondo il modello Client/Server, con le informazioni relative alle varie tipologie di dati che risiedono su un database Oracle, garantendo portabilità del sistema su qualsiasi tipo di stazione adeguatamente attrezzata. La componente Server è una macchina con sistema operativo Unix, predisposta con server http per rendere possibile l’interrogazione della macchina da utenze remote. Inoltre è prevista una base dati Oracle per l’archiviazione delle informazioni con precompilatore per codice C. Le componenti Client sono costituite da PC con almeno 16 Mb di RAM con sistema operativo Windows 95 o Windows NT e Netscape Navigator 3.0 o superiore. La procedura VDR, operativa su un’architettura di tipo Client/Server, con le informazioni concentrate sul Server, rende accessibile le informazioni a tutti gli utenti collegati in rete con un PC Client, ed al tempo stesso garantisce una sufficiente sicurezza e facilità di gestione 18 Terzo Capitolo Server Web, Java, CGI, Active X Server Web Un Server Web è un programma in funzione su una macchina direttamente connessa a Internet, in attesa che un browser Web si colleghi e richieda un file. Quando giunge tale richiesta, il server individua il file e lo invia al browser. Il Server Web e il browser Web comunicano utilizzando il protocollo HTTP (Hyper Text Transfer Protocol), un protocollo appositamente creato per il trasferimento di documenti ipertestuali su Internet. Solitamente i Server Web vengono chiamati HTTPD, dove la "D" finale sta per "daemon", termine UNIX che identifica un programma che funziona in background e rimane in attesa di richieste: quando un daemon riceve una richiesta, si risveglia, elabora tale richiesta e torna in background. Java Java è un linguaggio di programmazione simile al C++, portabile su qualunque sistema dotato di una apposita Macchina Java Virtuale in grado di interpretare il codice intermedio con cui è composto il linguaggio stesso. Il risultato è quello di avere programmi compatti, anche se talvolta lenti, che funzioneranno su qualunque tipo di PC. Il compilatore Java compila, infatti, il codice sorgente in una rappresentazione 19 intermedia chiamata “bytecode Java”. Il termine bytecode sta ad indicare che ogni parte di un programma Java viene tradotta in una sequenza di byte che rappresentano le istruzioni per una Macchina Java Virtuale Il codice di programma viene sempre controllato dalla Macchina Java Virtuale, senza la quale nessun programma Java può funzionare. Questa Macchina è integrata nel browser di Internet, oppure è installata come programma indipendente sul disco fisso. Nel primo caso i programmi Java non hanno possibilità di scrittura sul disco fisso e non possono nemmeno essere eseguiti programmi esterni. Nel secondo caso il programma Java viene prima caricato tramite Internet e poi eseguito con la Macchina Java Virtuale. Questa operazione non è automatica ed è quindi sotto il controllo esterno. I dati locali potranno essere letti e scritti solo previo autorizzazione esterna. CGI Gli script CGI (Common Gateway Interface) rappresentano un metodo utilizzato per eseguire sul server Web un programma che si basa sull’input fornito dal browser. Gli script CGI consentono di rendere interattive le pagine Web, ovvero di ricercare un oggetto in un database, di offrire commenti riguardanti ciò che si legge o di selezionare un oggetto da una scheda ottenendo una risposta specifica. Uno script CGI è semplicemente un programma in esecuzione su un server Web e che viene attivato dall’input fornito da un browser. Spesso lo script CGI rappresenta l’anello di congiunzione fra il server e qualche altra applicazione eseguibile sul sistema, ad esempio un database. Gli script CGI possono assumere diverse forme a seconda del supporto offerto dal server Web: possono essere programmi compilati o file batch o qualsiasi altro tipo di file eseguibile. Gli script CGI possono essere utilizzati in due modi: come azione (ACTION) di una scheda o come un link diretto ad una pagina. 20 Gli script CGI vengono richiamati dal server sulla base di informazioni ricevute dal browser: • Un indirizzo URL punta a uno script CGI nello stesso modo in cui potrebbe puntare a qualsiasi altro file situato sul server, ad esempio un documento o un’immagine. Normalmente l’indirizzo URL si trova nella parte ACTION di una scheda Web. Il browser richiede tale indirizzo URL al server così come farebbe con qualsiasi altro documento. • Il server riceve la richiesta, nota che l’indirizzo URL punta a un file script (sulla base del nome o della posizione in cui è memorizzato il file a seconda del server) ed esegue tale script. • Lo script esegue qualche azione sulla base dell’eventuale input ricevuto dal browser. L’azione può essere l’interrogazione di un database, il calcolo di un valore o semplicemente l’esecuzione di un altro programma installato sul sistema. • Lo script poi formatta il risultato in modo comprensibile per il server Web. • Il server Web riceve il risultato dallo script e lo trasmette al browser che lo formatta e visualizza per il lettore. Active X Gli Active-X Control non sono altro che programmi che vengono caricati tramite Internet ed eseguiti con Microsoft Internet Explorer. Come tutti gli altri programmi Windows, anche i programmi Active-X hanno accesso a tutte le risorse del sistema e possono eseguire qualsiasi operazione, ad esempio riprodurre un video o cancellare dei dati. In Active-X le brecce nella sicurezza sono già programmate nel concetto base. Se il programma si trova sul disco fisso, è fuori da ogni controllo esterno. Il programma Active-X viene attivato da un paio di semplici righe di codice HTML ed 21 entra in azione senza alcun intervento esterno. 22 Quarto Capitolo Conclusioni Se prendiamo in esame l’evoluzione degli elaboratori, anche solo facendo riferimento agli ultimi due o tre decenni, possiamo notare due fatti fondamentali strettamente collegati fra loro: l’aumento della potenza dell’hardware, e un continuo e veloce miglioramento delle modalità di comunicazione dell’uomo con la macchina. I linguaggi di programmazione e, in generale, gli ambienti di lavoro integrati, offrono all’utente un approccio “amichevole”, svincolandolo dalla gestione di molti problemi tecnici e permettendogli di concentrarsi soprattutto sulla logica delle applicazioni. Il prossimo obbiettivo, ancora in fase di studio, è quello di produrre computer capaci di misurarsi cin l’intelligenza e le conoscenze proprie della mente umana. Si vuole che l’utente possa dialogare con il computer senza essere più costretto allo sforzo di adattamento che invece è ancora oggi necessario. Per raggiungere questo scopo, non basta aumentare la potenza delle macchine o perfezionare il software; si tratta, invece, di progettare elaboratori che abbiano un’architettura più attuale, con molti processori, in modo che sia possibile ottenere sistemi intelligenti basati sulla conoscenza. Proprio intorno a questo obbiettivo ruotano i programmi di ricerca rivolti alla progettazione degli elaboratori della Quinta Generazione. 23 Una caratteristica fondamentale dei nuovi sistemi di elaborazione è costituita da una base della conoscenza, di grandi dimensioni e sottoposta a un continuo aggiornamento, realizzato da un sottosistema di processori. Naturalmente, nasce il problema di mettere a punto tecniche valide per strutturare e memorizzare questa conoscenza, in modo che sia possibile consultarla e aggiornarla in tempi accettabili. Per imitare il funzionamento della mente umana, occorre che la macchina abbia la capacità di comprendere la descrizione di un problema e di progettarne la soluzione. Il grande passo in avanti consisterebbe nel dare all’utente la possibilità di formulare quesiti in linguaggio naturale, senza l’obbligo di formalizzarli secondo schemi rigidi, come quelli imposti dai sistemi attuali. E’ di particolare importanza, allora, riuscire a riprodurre certi meccanismi di ragionamento e di apprendimento. Per questo motivo, un elemento fondamentale nell’architettura dei nuovi calcolatori è rappresentato da un sottosistema di processori dedicato all’inferenza, cioè al processo attraverso il quale un elaboratore ricava delle conclusioni sulla base di un certo insieme di conoscenze (sono tecniche tipicamente usate nel campo dell’intelligenza artificiale). Addirittura, la potenza di un computer di questo tipo viene espressa in lips (inferenze logiche per secondo). Proprio allo scopo di ottenere un livello più elevato di prestazioni, molti studi puntano alla realizzazione di nuove tecniche per le elaborazioni in parallelo. Con il termine processo si intende un programma in esecuzione, e si ha un parallelismo reale quando, in presenza di più processori, avviene l'esecuzione contemporanea di più processi. Addirittura, lo stesso processo può essere scomposto in più parti, che vengono poi eseguite nello stesso tempo. Tuttavia, non sempre tutti i processi e tutte le istruzioni di un processo possono essere eseguite nello stesso tempo, e per utilizzare in modo efficiente le possibilità di elaborazioni in parallelo, occorrono sistemi di gestione molto sofisticati. 24 Un altro campo di ricerca che desta grande interesse è quello che riguarda le modalità di comunicazione tra il computer e i suoi utenti. L'obbietttivo di creare un'interfaccia intelligente, che permetta l'uso di immagini e di linguaggi naturali (o, almeno, di loro sottoinsiemi), assume molta importanza soprattutto in previsione di un'utenza sempre più vasta, formata anche da persone non esperte. L'interpretazione automatica di un linguaggio naturale presenta molte difficoltà, perchè spesso accade che una frase abbia più interpretazioni possibili. Mentre, per un essere umano è generalmente possibile scegliere l'interpretazione giusta in base al contesto, ciò non è altrettanto facile quando si applicano procedimenti automatici, anche nel caso in cui si operi con un vocabolario più ristretto. D'altra parte, per poter comunicare con un elaboratore in un linguaggio naturale, occorrerebbe "istruirlo" a interpretare il significato delle frasi e a fornire risposte appropriate, sempre nello stesso linguaggio. 25 Appendice A Codice sorgente Java import java.awt.*; import java.io.*; import jdbc.sql.*; import jdbc.math.*; public class Connection { private static Connection conn; private static Statement stmt_S; private static Statement stmt_I; private static Statement stmt_D; private static Statement stmt_U; public static void Connection() { String driver_class = "oracle.jdbc.dnlddriver.OracleDriver"; String connect_string = "jdbc:oracle:dnldthin:@rs4edp:1521:MIDACON"; try { if (conn == null) { System.out.println("Load the JDBC driver"); 26 Class.forName (driver_class); System.out.println("Connect to the database "+connect_string); conn = DriverManager.getConnection (connect_string, "system", "manager"); System.out.println("Connect to the database "+connect_string+ "done"); stmt_S = conn.createStatement (); stmt_I = conn.createStatement (); stmt_D = conn.createStatement (); stmt_U = conn.createStatement (); } } catch (Exception e) { System.out.println("error "+e); } } public static ResultSet Search(String query) { ResultSet rset; try { rset=stmt_S.executeQuery(query); } catch (Exception e) { System.out.println(e.getMessage()); errore error=new errore(new Frame()); error.campo1.setText("ERRORE:"); error.campo2.setText(e.getMessage()); error.show(); 27 } return rset; } public static boolean Insert(String query) { try { ResultSet rset=stmt_I.executeQuery (query); return(true); } catch (Exception e) { System.out.println(e.getMessage()); if (e.getMessage().startsWith("ORA-00001")) { errore error=new errore(pri.app); error.campo1.setText("Errore"); error.campo2.setText("Record gia esiste"); error.show(); } else { errore error=new errore(pri.app); error.campo2.setText(e.getMessage()); error.show(); } return(false); } } 28 public static boolean Update(String query) { try { ResultSet rset=stmt_U.executeQuery (query); return(true); } catch (Exception e) { if (e.getMessage().startsWith("ORA-00001")) { errore error=new errore(pri.app); error.campo1.setText("Errore"); error.campo2.setText("Record gia esiste"); error.show(); } else { errore error=new errore(pri.app); error.campo2.setText(e.getMessage()); error.show(); } return(false); } } public static boolean Delete(String query) { try { ResultSet rset=stmt_D.executeQuery (query); return(true); 29 } catch (Exception e) { System.out.println(e.getMessage()); errore error=new errore(new Frame()); error.campo2.setText(e.getMessage()); error.show(); return(false); } } } 30 import java.awt.*; import java.util.*; import java.io.*; import java.net.*; import jdbc.sql.*; public class Client_VDR { private static Socket channel=null; private static DataOutputStream os=null; private static DataInputStream is=null; final static String size_header="2"; final static String size_data="1"; final static String height="30"; private static Hashtable sez_descr=new Hashtable(); private static int righe_IMP2,righe_IMP3,righe_IMP4,righe_IMP5; private static byte TDIMP_height=25; private static byte num_righe=24; private static StringTokenizer list[]=new StringTokenizer[3]; private static void THVDR_List(String comm,DataOutputStream os) throws Exception { os.writeBytes("<tr align=\"center\" valign=\"top\">\n"); os.writeBytes("<th rowspan=1 colspan=8>\n"); os.writeBytes("<table noborder align=\"center\" cellspacing=\"0\" cellpadding=\"6\" bordercolor=\"Black\">\n"); os.writeBytes("<tr align=\"center\">\n"); os.writeBytes("<td rowspan=2 colspan=1 valign=\"top\" height=\""+height+"\"><img 31 src=\"ge.gif\"><img src=\"Sprite7.gif\"><br>Firenze</td>\n"); os.writeBytes("<td rowspan=1 colspan=1 valign=\"top\" height=\""+height+"\"><EM><B><FONT size=6>\n"); os.writeBytes("VENDOR DOCUMENT LIST\n"); os.writeBytes("</FONT></B></EM></td>\n"); os.writeBytes("</tr>\n"); os.writeBytes("<tr align=\"center\">\n"); .writeBytes("<td align=\"left\" height=\""+height+"\"><EM><B><FONT size=4>\n"); os.writeBytes("N° Commessa N.P. :"+comm+"\n"); os.writeBytes("</FONT></B></EM></td>\n"); os.writeBytes("</tr>\n"); os.writeBytes("</table>\n"); os.writeBytes("</th>\n"); os.writeBytes("</tr>\n"); os.writeBytes("<tr align=\"center\" valign=\"top\">\n"); os.writeBytes("<th rowspan=1 colspan=1 height=\"60\" width=\"60\"><font size=\""+size_header+"\"><b><i>Posizione</i></b></font></th>\n"); os.writeBytes("<th rowspan=1 colspan=1 height=\"60\" width=\"280\"><font size=\""+size_header+"\"><b><i>Titolo</i></b></font></th>\n"); os.writeBytes("<th rowspan=1 colspan=1 height=\"60\" width=\"100\"><font size=\""+size_header+"\"><b><i>N° Documento<br>NP</i></b></font></th>\n"); os.writeBytes("<th rowspan=1 colspan=1 height=\"60\" width=\"100\"><font size=\""+size_header+"\"><b><i>N° Documento<br>Cliente</i></b></font></th>\n"); os.writeBytes("<th rowspan=1 colspan=1 height=\"60\" width=\"100\"><font size=\""+size_header+"\"><b><i>Descrizione<br>Documento<br>informatico</i></b></font> </th>\n"); os.writeBytes("<th rowspan=1 colspan=1 height=\"60\" width=\"50\"><font 32 size=\""+size_header+"\"><b><i>Penale</i></b></font></th>\n"); os.writeBytes("<th rowspan=1 colspan=1 height=\"60\" width=\"70\"><font size=\""+size_header+"\"><b><i>Pagamento</i></b></font></th>\n"); os.writeBytes("<th rowspan=1 colspan=1 height=\"60\" width=\"30\"><font size=\""+size_header+"\"><b><i>Note</i></b></font></th>\n"); os.writeBytes("</tr>\n"); } private static void THVDR_Note(String comm,DataOutputStream os) throws Exception { os.writeBytes("<tr align=\"center\" valign=\"top\">\n"); os.writeBytes("<th rowspan=1 colspan=2>\n"); os.writeBytes("<table noborder align=\"center\" cellspacing=\"0\" cellpadding=\"6\" bordercolor=\"Black\">\n"); os.writeBytes("<tr align=\"center\">\n"); os.writeBytes("<td rowspan=2 colspan=1 valign=\"top\" height=\""+height+"\"><img src=\"ge.gif\"><img src=\"Sprite7.gif\"><br>Firenze</td>\n"); os.writeBytes("<td rowspan=1 colspan=1 valign=\"top\" height=\""+height+"\"><EM><B><FONT size=6>\n"); os.writeBytes("VENDOR DOCUMENT REGISTER\n"); os.writeBytes("</FONT></B></EM></td>\n"); os.writeBytes("</tr>\n"); os.writeBytes("<tr align=\"center\">\n"); os.writeBytes("<td align=\"left\" height=\""+height+"\"><EM><B><FONT size=4>\n"); os.writeBytes("N° Commessa N.P. :"+comm+"<br>NOTE :\n"); os.writeBytes("</FONT></B></EM></td>\n"); os.writeBytes("</tr>\n"); 33 os.writeBytes("</table>\n"); os.writeBytes("</th>\n"); os.writeBytes("</tr>\n"); os.writeBytes("<tr align=\"center\" valign=\"top\">\n"); os.writeBytes("<th rowspan=1 colspan=1 width=\"20%\" height=\""+height+"\"><font size=\""+size_header+"\"><b><i>N° nota</i></b></font></th>\n"); os.writeBytes("<th rowspan=1 colspan=1 height=\""+height+"\"><font size=\""+size_header+"\"><b><i>Nota</i></b></font></th>\n"); os.writeBytes("</tr>\n"); } public static void StampaVDR_List(Form1 app,StringTokenizer pr_doc,String comm) throws Exception { int righe_primapagina1=10; int righe_primapagina2=11; String st,query; ResultSet rset; int cont,origine; Hashtable ci_doc=new Hashtable(); boolean notEOS=false; channel=new Socket("rs3edp",22500); os=new DataOutputStream(channel.getOutputStream()); is=new DataInputStream(channel.getInputStream()); query="select ci_doc,descr from coddocinf_v"; rset=conect.Search(query); 34 while (rset.next()) ci_doc.put(rset.getString(1),rset.getString(2)); query="select pos,tit,cod_doc,ndoc_cl,ci_doc,pen_doc,pag_doc,note from gendoc_v where pr_doc in (-1"; while (pr_doc.hasMoreElements()) query=query+","+pr_doc.nextToken(); query=query+") order by pos asc"; rset=conect.Search(query); if (channel!=null && os!=null && is!=null) { query="select cod_not,descr from notecom_v where comm='"+comm+"' and cod_not in ('$$'"; os.writeBytes("INIZIO\n"); os.writeBytes("<html>\n"); os.writeBytes("<head>\n"); os.writeBytes("<title>Vendor Document List</title>\n"); os.writeBytes("</head>\n"); os.writeBytes("<body bgcolor=\"white\">\n"); os.writeBytes("<P align=center>\n"); os.writeBytes("<table border align=\"center\" cellspacing=\"0\" cellpadding=\"6\" bordercolor=\"Black\" width=\"100%\">\n"); THVDR_List(comm,os); cont=0; do { while ((notEOS=rset.next()) && (cont<righe_primapagina1)) { cont++; 35 os.writeBytes("<tr align=\"left\" valign=\"top\">\n"); os.writeBytes("<td rowspan=1 colspan=1 height=\""+height+"\" width=\"60\"><font size=\""+size_data+"\">"+(rset.getString(1)==null?"":rset.getString(1))+"</font></td>\n"); os.writeBytes("<td rowspan=1 colspan=1 height=\""+height+"\" width=\"280\"><font size=\""+size_data+"\">"+(rset.getString(2)==null?"-":rset.getString(2))+"</font></td>\n"); os.writeBytes("<td rowspan=1 colspan=1 height=\""+height+"\" width=\"100\"><font size=\""+size_data+"\">"+(rset.getString(3)==null?"-":rset.getString(3))+"</font></td>\n"); os.writeBytes("<td rowspan=1 colspan=1 height=\""+height+"\" width=\"100\"><font size=\""+size_data+"\">"+(rset.getString(4)==null?"-":rset.getString(4))+"</font></td>\n"); os.writeBytes("<td rowspan=1 colspan=1 height=\""+height+"\" width=\"100\"><font size=\""+size_data+"\">"+(rset.getString(5)==null?"-":((String) ci_doc.get(rset.getString(5))))+"</font></td>\n"); os.writeBytes("<td rowspan=1 colspan=1 height=\""+height+"\" width=\"50\"><font size=\""+size_data+"\">"+(rset.getString(6)==null?"":rset.getString(6))+"</font></td>\n"); os.writeBytes("<td rowspan=1 colspan=1 height=\""+height+"\" width=\"70\"><font size=\""+size_data+"\">"+(rset.getString(7)==null?"":rset.getString(7))+"</font></td>\n"); os.writeBytes("<td rowspan=1 colspan=1 height=\""+height+"\" width=\"30\"><font size=\""+size_data+"\">"+(rset.getString(8)==null?"":rset.getString(8))+"</font></td>\n"); os.writeBytes("</tr>\n"); 36 query=query+",'"+rset.getString(8)+"'"; } os.writeBytes("</table>\n"); os.writeBytes("<P/>\n"); os.writeBytes("<br>\n"); if (notEOS) { cont=1; os.writeBytes("<P align=center>\n"); os.writeBytes("<table border align=\"center\" cellspacing=\"0\" cellpadding=\"6\" bordercolor=\"Black\" width=\"100%\">\n"); THVDR_List(comm,os); os.writeBytes("</tr>\n"); os.writeBytes("<tr align=\"left\" valign=\"top\">\n"); os.writeBytes("<td rowspan=1 colspan=1 height=\""+height+"\" width=\"60\"><font size=\""+size_data+"\">"+(rset.getString(1)==null?"":rset.getString(1))+"</font></td>\n"); os.writeBytes("<td rowspan=1 colspan=1 height=\""+height+"\" width=\"280\"><font size=\""+size_data+"\">"+(rset.getString(2)==null?"-":rset.getString(2))+"</font></td>\n"); os.writeBytes("<td rowspan=1 colspan=1 height=\""+height+"\" width=\"100\"><font size=\""+size_data+"\">"+(rset.getString(3)==null?"-":rset.getString(3))+"</font></td>\n"); os.writeBytes("<td rowspan=1 colspan=1 height=\""+height+"\" width=\"100\"><font size=\""+size_data+"\">"+(rset.getString(4)==null?"-":rset.getString(4))+"</font></td>\n"); os.writeBytes("<td rowspan=1 colspan=1 37 height=\""+height+"\" width=\"100\"><font size=\""+size_data+"\">"+(rset.getString(5)==null?"-":((String) ci_doc.get(rset.getString(5))))+"</font></td>\n"); os.writeBytes("<td rowspan=1 colspan=1 height=\""+height+"\" width=\"50\"><font size=\""+size_data+"\">"+(rset.getString(6)==null?"":rset.getString(6))+"</font></td>\n"); os.writeBytes("<td rowspan=1 colspan=1 height=\""+height+"\" width=\"70\"><font size=\""+size_data+"\">"+(rset.getString(7)==null?"":rset.getString(7))+"</font></td>\n"); os.writeBytes("<td rowspan=1 colspan=1 height=\""+height+"\" width=\"30\"><font size=\""+size_data+"\">"+(rset.getString(8)==null?"":rset.getString(8))+"</font></td>\n"); os.writeBytes("</tr>\n"); query=query+",'"+rset.getString(8)+"'"; } } while (notEOS); query=query+") order by cod_not"; origine=2*righe_primapagina1; cont=cont % righe_primapagina1; if (cont==0) origine=0; for (int i=1;i<=(origine-cont*2);i++) os.writeBytes("<br>\n"); rset=conect.Search(query); 38 os.writeBytes("<P align=center>\n"); os.writeBytes("<table border align=\"center\" cellspacing=\"0\" cellpadding=\"6\" bordercolor=\"Black\" width=\"100%\">\n"); THVDR_Note(comm,os); cont=0; do { while ((notEOS=rset.next()) && (cont<righe_primapagina2)) { cont++; os.writeBytes("<tr align=\"left\" valign=\"top\">\n"); os.writeBytes("<td rowspan=1 colspan=1 width=\"20%\" height=\""+height+"\"><font size=\""+size_data+"\">"+(rset.getString(1)==null?"-":rset.getString(1))+"</font></td>\n"); os.writeBytes("<td rowspan=1 colspan=1 height=\""+height+"\"><font size=\""+size_data+"\">"+(rset.getString(2)==null?"":rset.getString(2))+"</font></td>\n"); os.writeBytes("</tr>\n"); } os.writeBytes("</table>\n"); os.writeBytes("<P/>\n"); os.writeBytes("<br>\n"); if (notEOS) { cont=1; os.writeBytes("<P align=center>\n"); os.writeBytes("<table border align=\"center\" cellspacing=\"0\" 39 cellpadding=\"6\" bordercolor=\"Black\" width=\"100%\">\n"); THVDR_Note(comm,os); os.writeBytes("<tr align=\"left\" valign=\"top\">\n"); os.writeBytes("<td rowspan=1 colspan=1 width=\"20%\" height=\""+height+"\"><font size=\""+size_data+"\">"+(rset.getString(1)==null?"-":rset.getString(1))+"</font></td>\n"); os.writeBytes("<td rowspan=1 colspan=1 height=\""+height+"\"><font size=\""+size_data+"\">"+(rset.getString(2)==null?"":rset.getString(2))+"</font></td>\n"); os.writeBytes("</tr>\n"); } } while (notEOS); os.writeBytes("</body>\n"); os.writeBytes("</html>"); os.writeByte('\n'); os.writeBytes("FINE"); os.writeByte('\n'); if ((st=is.readLine()) != null) { System.out.println(st); app.getAppletContext().showDocument(new URL("http://vdr/"+st),"report"); } } os.close(); 40 is.close(); channel.close(); 41 import java.awt.*; import java.io.*; import java.net.*; public class SimpleServer { public static void main(String[] args) { Socket channel; DataInputStream in; DataOutputStream out; ServerSocket server; boolean listening=true; String st,ind,path; OutputStream fi; int cont,port; try { port=22500; if (1<=args.length) port=Integer.parseInt(args[0]); path=""; if (2<=args.length) path=args[1]; server = new ServerSocket(port, 15); ind="0"; cont=0; 42 while (listening) { channel = server.accept(); out = new DataOutputStream(channel.getOutputStream()); in = new DataInputStream(channel.getInputStream()); if ((ind=in.readLine()) != null) { cont++; fi = new FileOutputStream("/u04/vdradm/web/doc/"+path+"file"+String.valueOf(cont)+".html"); while (((st=in.readLine()) != null) && (st.compareTo("FINE")!=0)) { byte buffer[]=new byte[st.length()]; for (int i=0;i<buffer.length;i++) buffer[i]=(byte) st.charAt(i); fi.write(buffer); fi.write((byte) '\n'); } fi.close(); } out.writeBytes(path+"file"+String.valueOf(cont)+".html"); out.writeByte('\n'); out.close(); in.close(); } } catch (IOException e) { System.err.println("I/O failed on the connection to: rs3edp "+e); } } 43 Appendice B Il Calcolo della Riscrittura di Termini L'uso dei paradigmi di programmazione logica e funzionale, e più in generale dei linguaggi dichiarativi, come supporto per la definizione di un linguaggio di programmazione ha trovato negli ultimi 30 anni sempre maggior spazio fra le attività di ricerca. A differenza dei più comuni linguaggi di programmazione tradizionali (FORTRAN, Pascal, C), che sono basati sul paradigma imperativo, i linguaggi logici (generalmente linguaggi della Logica dei Predicati del Primo Ordine) adottano un modello dichiarativo di rappresentazione della realtà. Un programma scritto in un linguaggio di programmazione tradizionale consiste in una sequenza di istruzioni che specificano in modo estremamente dettagliato le operazioni necessarie per risolvere un dato problema; un linguaggio logico, invece, descrive astrattamente un dato problema attraverso un insieme di formule ben formate, senza precisare in modo particolareggiato una qualche procedura di calcolo per la sua risoluzione. In altre parole, un programma scritto in un linguaggio logico fornisce solamente la specifica dichiarativa di un dato problema, lasciando ad un suo esecutore la preoccupazione di provvedere al meccanismo di risoluzione, ovvero al motore inferenziale. I progressi ottenuti in questo campo, con la definizione del primo linguaggio di Programmazione Logica (PROLOG), hanno stimolato la ricerca sulle possibilità di adottare i linguaggi logici, e più in generale i linguaggi dichiarativi, come linguaggi 44 macchina per nuovi elaboratori; in particolare, i linguaggi dichiarativi sembrano offrire maggiori prestazioni rispetto ai linguaggi imperativi tradizionali nella progettazione di macchine parallele, combinando efficienza a livello hardware e facilità di programmazione a livello software. Le architetture parallele dell'attuale generazione sono caratterizzate da 3 operazioni fondamentali, in base alle quali possono essere classificate: • assegnamento dei lavori ai processori disponibili, che possono lavorare in parallelo; • comunicazione fra i vari processori; • controllo dell'esecuzione di un lavoro. La cosiddetta granularità rappresenta la dimensione dei lavori assegnati ai vari processori: il parallelismo a grana fine utilizza lavori di dimensioni molto piccole (spesso una singola istruzione), che necessitano di modificare costantemente i dati, mentre il parallelismo a grana grossa usa lavori dimensionalmente ampi che raramente hanno bisogno di cambiare i dati. Le architetture a grana fine sono tipicamente costituite da molti elementi opportunamente collegati, e per questo richiedono un'efficiente comunicazione fra i vari processori: generalmente i vari processori possono modificare direttamente i dati, come in una struttura Pipeline o in systolic arrays, muovendo i dati lungo percorsi prestabiliti. Le architetture a grana grossa, invece, prevedono raramente il trasferimento dei dati e possono, perciò, essere realizzate anche con risorse per la comunicazione tipicamente responsabili del cosiddetto "collo di bottiglia di Von Neumann", come memorie condivise, buses, e reti. Osserviamo, infine, che il controllo dell'esecuzione di un lavoro può essere o centralizzato (SIMD, Single Instruction stream, Multiple Data stream), con un'unità di controllo che comunica le stesse istruzioni a tutti i processori, oppure distribuito (MIMD, Multiple Instruction stream, Multiple Data stream), dove ogni processore esegue la propria sequenza di istruzioni sui propri 45 dati. Le macchine a grana fine supportano il parallelismo SIMD, mentre quelle a grana grossa supportano il parallelismo MIMD. L'esperienza mostra che esistono problemi localmente omogenei, per i quali cioè più istanze di una singola istruzione possono essere applicate simultaneamente a più parti di uno stesso dato (adatti ad un parallelismo SIMD), e problemi globalmente inomogenei, composti da sottoproblemi differenti con poche caratteristiche in comune (adatti ad un parallelismo MIMD). Per tale classe di problemi la soluzione ottimale è rappresentata da macchine a multi-grana, che gestiscono in modo MIMD più processori, ognuno dei quali lavora in modo SIMD indipendentemente dagli altri. Il maggior ostacolo per un effettivo uso delle macchine parallele è rappresentato dalla difficoltà di una loro programmazione: esiste, infatti, un vuoto ("gap") fra le macchine parallele e i linguaggi di programmazione ad alto livello. Fra gli attuali modelli di calcolo quelli alla Von Neumann e i relativi linguaggi imperativi non possono efficientemente supportare il parallelismo, in quanto sono inerentemente sequenziali: i programmi scritti in linguaggi imperativi paralleli sono difficili da comprendere e mettere a punto, e sono legati alle risorse hardware disponibili. I modelli di calcolo dichiarativi, invece, presentano il vantaggio di non richiedere ordini specifici di esecuzioni per rendere esplicito il loro parallelismo, e i programmi scritti nei relativi linguaggi dichiarativi sono facilmente trasportabili, in quanto indipendenti dalle risorse hardware disponibili. In questo contesto, particolarmente importanti sono gli studi sul Calcolo della Riscrittura di termini: da una parte, infatti, il Calcolo della Riscrittura gioca un ruolo storicamente fondamentale nella formalizzazione della nozione di computabilità, essendo equivalente alle Macchine di Turing, agli Algoritmi di Markov, ecc..., dall'altra offre la possibilità di realizzare più modelli di calcolo in parallelo. Intuitivamente, il Calcolo della Riscrittura appare come una restrizione 46 del Calcolo del Rimpiazzamento di Eguali con Eguali: in tale Teoria si definisce una regola di inferenza, detta riscrittura, che permette la sostituzione "unidirezionale" di termini sintatticamente diversi, ma semanticamente uguali. La progettazione di una macchina dedicata al Calcolo della Riscrittura richiede lo sviluppo di nuovi modelli di esecuzione, in generali più complicati di quelli che supportano i linguaggi imperativi: in particolare, per esempio, viene abbandonato il concetto tradizionale di "memoria", e l'operazione fondamentale dei linguaggi imperativi, cioè l'assegnamento o memorizzazione, viene sostituita dalla relazione di matching. Da una parte si confida nella possibilità di superare il collo di bottiglia di Von Neumann, tipico dei sistemi di calcolo tradizionali, eliminando la separazione fisica fra processori e memoria, e quindi la condivisione delle "risorse per la comunicazione", responsabili di code di richieste di comunicazione fra le varie unità di un calcolatore: l'idea chiave è pensare ad un'elaborazione locale dei dati, ovvero ad un'elaborazione dei dati esattamente dove sono memorizzati. Dall'altra l'eliminazione di programmi di interfaccia, quali interpreti e traduttori, può realizzare l'idea di una macchina capace di "eseguire" direttamente programmi ad alto livello. Il Calcolo della Riscrittura presenta 4 modelli di computazione dichiarativi: • la Riscrittura Concorrente, che permette l'applicazione contemporanea di più regole in più parti di un dato; • la Riscrittura Parallela, che consente l'applicazione simultanea di una singola regola in più parti di un dato; • la Riscrittura Sequenziale, che applica una regola per volta in una singola parte di un dato; • la Riscrittura Parallela Partizionata (Associativa), che suddivide un dato in un certo numero di dominii omogenei su ognuno dei quali è realizzata la Riscrittura Parallela generalmente con regole differenti per ogni differente 47 dominio. La Riscrittura Concorrente potrebbe essere realizzata attraverso un'architettura MIMD, mentre la Riscrittura Parallela attraverso un'architettura SIMD; la Riscrittura Sequenziale corrisponde al tradizionale modello di calcolo di Von Neumann, e la Riscrittura Parallela Partizionata presenta un parallelismo SIMD a livello locale, e un parallelismo MIMD a livello globale, e quindi un parallelismo nel complesso multi-grana. In un precedente lavoro abbiamo presentato un'architettura di una macchina per l'implementazione del Calcolo della Riscrittura: la Macchina a Riduzione, o Reduction Machine (RM). Ricollegandoci a precedenti studi sulla definizione di macchine per l'unificazione in parallelo, abbiamo descritto una Macchina che realizza secondo una tecnica associativa la riduzione di un termine in forma normale rispetto ad un sistema di riscrittura terminante, confluente, e lineare a sinistra e a destra. Il progetto della Reduction Machine estende, attraverso un'architettura a Pipeline o systolic arrays, nella quale i dati si muovono lungo percorsi prestabiliti, la potenziale efficienza del parallelismo a grana fine a computazioni globalmente inomogenee, partizionando dinamicamente i dati in dominii omogenei, ognuno dei quali può essere elaborato all'interno di un singolo blocco Rule. 48 Bibliografia [1] Cerabolini L. (1995), “Le reti”, Jackson Libri S.r.l. [2] Ghislandi P., Esposito A., Pozzoli G. (1996), “Didattica a distanza. Il progetto MOEBIUS, sociologia on-line all’Università di Milano”, CTU NotizieUniversità degli Studi di Milano. [3] Lemay L. (1997), “HTML 3.2”, McGraw-Hill Libri Italia S.r.l. [4] Margarita S. (1996), “Un’esperienza di formazione multimediale: Multimedia Mathematics”, atti del Convegno “Rota ‘96-La formazione e il lavoro al tempo delle reti telematiche”, Torino , 23 novembre 1996. [5] [6] Naughton P. (1996), “Il manuale Java”, McGraw-Hill Libri Italia S.r.l. Schank J. D. (1996), “Il manuale Client/Server. Architettura e Applicazioni”, McGraw-Hill Libri Italia S.r.l. 49 50