Diagramma delle classi
Transcript
Diagramma delle classi
Realizzato da: Enrico Maria Caruso Fabio Affè Indice Introduzione: Cos’è Gossip? Obiettivi del testo Contenuto delle varie sezioni Dettagli Implementativi: Strumenti e tecniche adottate Struttura del progetto - Diagramma delle classi: - Dettagli realizzativi delle classi principali - Breve descrizione delle classi di appoggio - Diagramma delle attività - Diagramma dei casi d’uso - Narrazione dei casi d’uso - Diagrammi di sequenza relativi ad ogni caso d’uso. Architettura del Sistema Dislocazione dei componenti Guida per l’utente amministratore Funzionalità e servizi del BootStapServer e dei MessageServer Attivazione del registry RMI Attivazione del MessageServer e del BootStrapServer Guida per l’utente generico Passi principali Avvio del Client Presentazione interfaccia Sviluppi futuri Bibliografia Introduzione: Cos’è Gossip? Gossip è un software che fornisce un servizio di scambio messaggi in tempo reale fra utenti connessi in rete ed un servizio email-like per gli utenti offline. Obiettivi del testo Lo scopo di questo testo è di illustrare brevemente le varie fasi che hanno portato alla realizzazione del progetto descrivendo i file sorgente e le strutture dati utilizzate. Fornisce inoltre le informazioni necessarie all'utilizzo di Gossip sia per gli amministratori della rete che per gli utenti generici. Contenuto delle varie sezioni Il presente testo si divide in quattro sessioni principali: Dettagli implementativi: che descrive le tecniche e gli strumenti usati, fornisce un’ analisi dettagliata della struttura del progetto mediante diagrammi UML, spiega il funzionamento delle classi principali, e illustra l’esecuzione dei thread mediante diagrammi di sequenza Architettura: che illustra attraverso le viste ibride (UML) la dislocazione dei componenti software e hardware di Gossip. Guida per l’amministratore: che mostra informazioni riguardante il modo di compilazione e di esecuzione del codice relativo ai servers (BootStrapServer e MessageServer). Guida per l’utente generico: che mostra come va compilato ed eseguito il client Gossip e ne descrive le principali funzionalità. Dettagli Implementativi Strumenti e tecniche adottate Il progetto “Gossip” è stato realizzato utilizzando principalmente gli strumenti forniti dal centro di calcolo quali le macchine dei laboratori e la rete del polo Fibonacci. Per la stesura del codice è stato usato l’ambiente di sviluppo eclipse su workstation linux utilizzando le principali tecniche di programmazione di rete. Tra le tecniche adottate citiamo RMI, i protocolli TCP e UDP ed il Multicast. Struttura del progetto La realizzazione di programmi che lavorano in rete come tutta la programmazione ad oggetti in genere comporta scelte progettuali impegnative che riguardano vari ambiti. La ricerca e la creazione di nuovi oggetti che semplificano la gestione ed il trattamento dei dati, così come la scelta dei metodi di comunicazione è spesso ardua e di gran lunga più dispendiosa in termini di tempo rispetto alla programmazione vera e propria. Nella realizzazione di Gossip abbiamo cercato di sfruttare al massimo le conoscenze acquisite durante il corso combinandole con quelle dei corsi precedenti. Abbiamo semplificato al massimo la fase di scrittura del codice scegliendo le strutture dati più adeguate alle nostre esigenze e modellando su carta le varie funzionalità da implementare prima della vera e propria programmazione. • Diagramma delle classi Fig.1 GOSSIP: Diagramma delle Classi Di seguito verranno descritte le classi che compongono Gossip con particolare enfasi sulle principali scelte di progetto effettuate. Dettagli realizzativi delle classi principali BootStrapServer Crea un nuovo oggetto server di tipo BootStrapServerImpl su cui effettua il Naming.rebind per aggiungerlo al registro RMI. BootStrapServerImpl La classe presenta metodi RMI messi a disposizione ai client GOSSIP. Il costruttore crea un vettore ClientList, ed un file (struttura.txt) dove vengono salvate tutte le info su ogni utente che si registra. La classe consta dei seguenti metodi sincronizzati: doRegistrazione Metodo in RMI che permette di fare la registrazione di un utente. Il metodo controlla se l'utente e' gia' registrato accedendo al file struttura.txt, se non lo e' viene registrato altrimenti manda al client un messaggio con la frase: “Ti sei gia' registrato con questo nome” doLogin Permette di fare il login ad un utente. Il metodo controlla se l'utente e' registrato accedendo al file struttura.txt, se e' loggato, e procede di conseguenza aggiornando il file contatti.txt e informando gli altri Client interessati dell'avvenuto cambiamento di stato (CallBack RMI). A login effettuato viene assegnato al Client un MessageServer per i messaggi offline e vengono inviate a tale MessageServer le informazioni sul client sotto forma di Messaggio (vedi descrizione della classe) doLogout Permette di fare il logout ad un utente Il metodo modifica lo stato dell’utente nel file struttura.txt e nel file contatti.txt, successivamente informa gli altri Client interessati dell'avvenuto cambiamento di stato mediante l’uso di CallBack RMI. doVerificaContattoIn Permette di aggiungere un utente nella lista dei contatti di ingresso controllando se il contatto che voglio aggiungere e' registrato e aggiorna il file contatti.txt doVerificaContattoOut Permette di aggiungere un utente nella lista contatti di uscita. Controlla se l'utente che voglio aggiungere e' registrato e se l’utente mi ha già inserito tra i suoi contatti in entrata e aggiorna il file contatti.txt doCallbacks Questo metodo e' usato per informare tutti gli utenti registrati dei cambiamenti di stato dei loro contatti. Client La classe Client contiene il metodo main che lancia l’interfaccia grafica di Gossip e gestisce gli eventi generati dai pulsanti dell’interfaccia utente Gossip. Mantiene “chats” un array di ChatElement (vedi descrizione della classe, pag. 7) contenente le chat attualmente in esecuzione. Implementa anche il metodo vectorToJTextArea che viene usato per convertire la lista dei contatti fornita dal server al login nell’elenco dei contatti della JTextArea dell’interfaccia grafica. Questo metodo permette di scrivere gli elementi da un vettore di Utenti ad un oggetto JTextArea per la visualizzazione dei contatti. I contatti online verranno indicati con un simbolo “+”. ClientImpl La classe presenta i seguenti metodi: setStato permette di settare lo stato dell'utente al valore passato come parametro name ritorna il nome dell’utente ip ritorna l’indirizzo ip dell’host su cui si trova dell’utente stato ritorna lo stato in cui si trova l’utente callback notifica all’utente il cambio di stato dei sui contatti notifyMe viene utilizzato dal Server quando vuole notificare un messaggio all’utente. I messaggi di notifica vengono poi visualizzati su un’etichetta nell’interfaccia grafica del Client. Chat Serve per la comunicazione realtime tra due Utenti, la connessione è stata implementata con il protocollo Tcp. Il thread Chat lancia un’interfaccia grafica che permette all’utente di inviare messaggi e di visualizzare quelli ricevuti. Per la ricezione di messaggi crea e lancia il thread Lettura (descritto di seguito). Lettura Thread, lanciato da chat, che resta in attesa di leggere i messaggi di testo inviati su una socket. Chi invia è l’utente con cui ho instaurato una connessione Tcp. Implementa il metodo esci() che termina il thread. MessaggiOffline Questa classe permette la comunicazione tra l’utente e il messageserver. Lancia un’interfaccia grafica che permette all’utente di scrivere i propri messaggi ad un utente che al momento non è in linea. MessaggiOffline comunica direttamente con il MessageServer inviando pacchetti Udp sulla porta su cui il thread SalvaMessaggi (lanciato dal MessageServer al suo avvio) è in attesa. L’interfaccia è formata da una JTextArea e da due pulsanti (“Esci” e “Invia”). “Invia” non fa altro che prendere il testo dalla TextArea incapsularlo in un oggetto Messaggio (vedi descrizione della classe, pag. 8) e spedirlo al messageserver. “Esci” chiude semplicemente la finestra. LeggiMessaggiOffline ha lo scopo di far apparire sullo schermo dell’utente una finestra contenente tutti i messaggi che gli sono stati inviati quando non era in linea MessageServer Crea e lancia il thread SalvaMessaggi e il thread RecuperoMessaggi. Crea un collegamento multicast ed entra a farne parte dopo di che si mette in attesa di messaggi. I messaggi attesi sono: “Dammi” Inviato dal BootStrapServer, il MessageServer risponderà il numero di righe presenti nel “nomefile.txt” creato al suo avvio (nomefile è il nome del file passato da riga di comando, vedi pag. 22). Il BootStrapServer potrà così scegliere il MessageServer da assegnare al Client minimizzandone il carico. “Ric” seguito dal nome del contatto Inviato da RecuperoMessaggio in multicast a tutti i MessageServer per chiedere tutti i messaggi che sono destinati al contatto. Tali messaggi verranno inviati a RecuperoMessaggio già formattati per la stampa a video. Se riceve un messaggio diverso dai precedenti vuol dire che il BootStrapServer stà effettuando il login di un utente ed ha perciò inviato una stringa contenente le informazioni sul client sottoforma di Messaggio. Il MessageServer, dopo aver inviato una richiesta (“Ric”+nome contatto) in multicast a tutti gli altri MessageServer, sarà quindi in grado di rispondere direttamente al client con i messaggi ricevuti. RecuperoMessaggio E’ un thread lanciato dal MessageServer con il nome e l’ip dell’utente destinatario dei messaggi che il MessageServer intende recuperare come parametri. Invia a tutti i message server, compreso se stesso, in multicast, una richiesta di messaggi appartenti all'utente ed attende le risposte che formatta in una stringa ed invia al client in UDP. SalvaMessaggi E’ un thread lanciato dal MessageServer. Ha il compito di scrivere su file i messaggi inviati dai client che sono stati assegnati al MessageServer verso altri utenti non loggati in quel momento. Resta in attesa di riceve datagrammi, contenenti il messaggio da formattare e salvare, sulla porta 15000, dopo aver salvato il messaggio si rimette in attesa. ThreadAccept Ha lo scopo di accettare le connessioni TCP provenienti dagli altri utenti che vogliono avviare una chat con il Client. Va in attesa di connessioni sulla porta 40000, ogni volta che accetta una connessione aggiunge all’array di ChatElement “chats”, del Client, un nuovo oggetto contenente un thread Chat ed avvia tale thread per gestire la comunicazione. Dopodichè si rimette in attesa di nuove connessioni. Breve descrizione delle classi di appoggio ChatElement Permette di contenere oggetti di tipo Chat assieme agli InetAddress dei client interessati ed al nome del destinatario della comunicazione. Gli oggetti di questo tipo verranno gestiti dal Client nell’array chats. Questo permette ad un utente di avviare contemporaneamente più Chat verso gli amici con cui vuole scambiare informazioni e di identificare tali chat univocamente all’interno dell’array. L’identificazione univoca di una chat è indispensabile per la chiusura della chat stessa, infatti se uno dei due utenti interessati nella comunicazione chiude la propria schermata di chat essa verrà chiusa anche nell’altro host. Questa classe presenta il metodo whereIsInChats che permette di conoscere in che posizione di chats è presente una Chat verso l'utente destinatario passato come parametro. E’ così possibile impedire ad un utente di aprire più chat con lo stesso destinatario. ListaContatti E’ un oggetto dove vengono memorizzate le informazioni riguardanti i contatti di ingresso, di uscita e il message server assegnato ad un utente (proprietario). Questa struttura funge da appoggio a diverse classi e contiene: contattiin: un vettore che conterrà i contatti di ingresso contattiout: un vettore che conterrà i contatti di uscita proprietario: una stringa che rappresenta in proprietario di tali variabili msgServAss: una stringa che rappresenta il message server assegnato al proprietario Nel costruttore vengono inizializzate tali variabili. Abbiamo deciso di implementare tale oggetto per facilitare l’invio delle informazioni necessarie al Client da parte del BootStrapServer (Es: nel login). La classe ListaContatti presenta i metodi di seguito descritti: stringToListaContatti converte un oggetto di tipo stringa in un oggetto di tipo ListaContatti, la stringa passata come parametro deve essere adeguatamente formattata. Es: proprietario*contattoin1*..*contattoinN*$*contattoout1*..*contattooutN* ListaContattiToString converte un oggetto di tipo ListaContatti in un oggetto di tipo Stringa, la stringa risultante è formattata nel seguente modo: proprietario*contattoin1*..*contattoinN*$*contattoout1*..*contattooutN* containsIn controlla se nel vettore contattiin è già presente un contatto uguale a quello che voglio inserire containsOut controlla se nel vettore contattiout è già presente un contatto uguale a quello che voglio inserire containsIpInOut controlla se nel vettore contattiout è già presente un contatto con indirizzo ip uguale a quello che voglio inserire whereIsInOut trova la posizione nel vettore contattiout che contiene l’utente con nome uguale a quello passato come parametro al metodo Messaggio Questa classe rappresenta una struttura che incapsula oltre al messaggio che un mittente spedisce ad un destinatario, anche le informazioni del mittente e del destinatario. Per informazioni si intende il nome del mittente e del destinatario del messaggio ed i loro indirizzi ip. Principalmente viene usata per i messaggi offline (classe descritta a pag. 6)ed anche per altre operazioni. Questa struttura contiene: nomeMittente: che rappresenta il nome del mittente del messaggio, in forma testuale nomeDestinatario: che rappresenta il nome del destinatario del messaggio, in forma testuale msg: rappresenta il messaggio da spedire ipMitt: rappresenta l'indirizzo ip del mittente Dest: rappresenta l'indirizzo ip del destinatario e presenta i seguenti metodi: msgToByte permette di trasferire un oggetto di tipo Messaggio in un array di byte, l’operazione viene eseguita chiamando il metodo getBytes() su una stringa formattata nel seguente modo: nomeMittente*nomeDestinatario*msg*ipMitt*ipDest stringToMsg permette di trasformare una stringa in un oggetto di tipo Messaggio, la stringa passata deve essere formattata come sopra byteToMsg è l’operazione inversa di msgToByte, come parametro riceve un array di byte e lo converte in un oggetto di tipo Messaggio mettendo nei vari campi i rispettivi valori Utente È una struttura contenente le informazioni di ogni utente quali: il nome (name), l’indirizzo ip (ip) dell’host su cui si trova in quel momento e lo stato (loggato) in cui si trova in quel momento (loggato o non loggato), la classe presenta i metodi illustrati di seguito: stringToUtente questo metodo permette di trasformare una stringa in un oggetto utente, la stringa è formattata nel modo seguente: “name ip loggato” sameName permette di confrontare il campo “nome” di due oggetti Utente getName ritorna il valore del campo nome dell’Utente getIp ritorna il valore del campo ip dell’Utente toString override del metodo toString, chiamato su un oggetto Utente ritorna la stringa formattata nel modo seguente: “name ip loggato” Adattatore & AdattatoreChat Queste classi hanno lo scopo di gestire la chiusura della finestra quando si preme il tasto "X" in alto a destra. Adattatore controlla se l’utente non è loggato altrimenti effettua il logout prima di uscire. AdattatoreChat svolge invece le stesse azioni del pulsante chiudi di Chat. Help Gestisce l’help in linea di Gossip. • Diagramma delle Attività Di seguito viene mostrata un diagramma UML rappresentante l’intera attività che un utente può svolgere durante l’utilizzo di Gossip. Il diagramma delle attività non si presta in modo eccellente alla modellazione di alcune parti, come la chiusura, che può essere un’attività svolta in qualsiasi momento. Fig.2 GOSSIP: Diagramma delle Attività • Diagramma dei Casi d’uso Fig.3 GOSSIP: Diagramma dei Casi D’uso Il diagramma mostra, tutti i casi d’uso che interessano l’attore Utente. • Narrazione dei Casi d’uso Nome: Registrazione Breve descrizione: l'utente si registra Attori: Utente Precondizioni: / Passi Principali: 1 L'utente sceglie un nickname e lo fornisce al sistema. 2 Il sistema verifica l'unicità del nickname. 3 In caso positivo preleva l'IP dell'utente e lo memorizza assieme al nick ed allo stato nel database. Postcondizioni: Utente Registrato Situazioni Eccezionali: è impossibile accedere al database degli info degli utenti Nome: Login Breve descrizione: L'utente accede al sistema Gossip Attori: Utente Precondizioni: L'utente è registrato e non loggato Passi Principali: 1 L'utente inserisce il nickname per accedere al sistema. 2 Se il nickname è riconoscibile il sistema 2.1 Logga l'utente, modificando il suo stato nel database contenente le info degli utenti e nel database contente i contatti. 2.2 Sceglie un message server da associare all'utente. Se non c'è nessun message server lo comunica all'utente altrimenti verifica se ci sono messaggi in entrata non ancora letti e li comunica all'utente. 2.3 Aggiorna lo stato degli utenti presenti nelle liste contatti. Postcondizioni: L'Utente è loggato Situazioni Eccezionali: è impossibile accedere al database degli info degli utenti o al database dei contatti Nome:Logout Breve descrizione: L'utente effettua il logout Attori: Utente Precondizioni: L'utente ha effettuato il login Passi Principali: 1 L'utente comunica al sistema che vuole effettuare il logout 2 Il sistema cambia lo stato dell'utente nel database contenente le info degli utenti e nel database contenentei contatti 3 il sistema comunica agli altri client interessati l'avvenuto cambiamento Postcondizioni: L'utente non è loggato Situazioni Eccezionali: è impossibile accedere al database degli info degli utenti o al database dei contatti Nome: AggiungiContattoIn Breve descrizione: l’utente aggiunge un contatto nella sua lista di contatti di ingresso Attori: Utente Precondizioni: L’utente è loggato Passi Principali: 1 L'utente inserisce il nickname da aggiungere 2 Il sistema controlla se il nick che si vuole aggiungere è di un contatto registrato 2.1 se è registrato controlla se è già stato aggiunto 2.1.1 se è già stato aggiunto informa l’utente 2.1.2 altrimenti aggiunge il contatto ed informa l’utente Postcondizioni: contatto aggiunto nella lista dei contatti in ingresso Situazioni Eccezionali: è impossibile accedere al database degli info degli utenti Nome: AggiungiContattoOut Breve descrizione: l’utente aggiunge un contatto nella sua lista di contatti di uscita Attori: Utente Precondizioni: L’utente è loggato Passi Principali: 1 L'utente inserisce il nickname da aggiungere 2 Il sistema controlla se il nick che si vuole aggiungere è di un contatto registrato 2.1 se è registrato controlla se l’utente che vuole inserire il contatto nella sua lista contatti di uscita è presente nella lista contatti di ingresso dell’altro 2.1.1 se non è presente aggiunge il contatto e informa l’utente 2.1.2 altrimenti informa l’utente Postcondizioni: contatto aggiunto nella lista dei contatti di uscita Situazioni Eccezionali: è impossibile accedere al database degli info degli utenti o al database dei contatti Nome: ParlaCon Breve descrizione: permette la chat con altri contatti. Attori: Utente Precondizioni: Utente loggato Passi Principali: 1 L'utente inserisce il nome del contatto con cui vuole chattare 2 il sistema controlla se il contatto esiste 3 se il contatto è online lancia un interfaccia che permette di comunicare con il contatto selezionato e instaura con esso una connessione. 4 Se il contatto non esiste il sistema lo comunica all'utente. Postcondizioni: utente è loggato Situazioni Eccezionali: 1 contatto non online 2 impossibile instaurare la connessione con il contatto online Sequenza alternativa eventi : contatto non online Breve descrizione: L'utente invia un messaggio ad un contatto non online. Attori: Utente Precondizioni: L'utente è loggato. Passi Principali: 1 Il sistema avvia una interfaccia che permette all'utente di comporre un messaggio. 2 L'utente compone un nuovo messaggio. 3 Il sistema invia il messaggio al message server dell'utente mittente. Postcondizioni: / Situazioni Eccezionali: non è possibile instaurare una connessione con il server dei messaggi Diagrammi di sequenza relativi ad ogni caso d’uso Il nostro obiettivo è quello di mostrare l’evoluzione dell’esecuzione dei thread, i diagrammi di sequenza si prestano bene per rappresentare ciò, anche se in alcuni casi, la modellazione richiede dei vincoli riguardanti la sequenza temporale dello svolgimento delle azioni, e modella una sincronizzazione dei thread, poco conforme alla realtà Fig.4 GOSSIP: Sequence Diagram Registrazione Fig.5: Sequence Diagram Login Fig.6 GOSSIP: Sequence Diagram ParlaCon Fig.7 GOSSIP: Sequence Diagram AggiungiContattoIn Fig.8 GOSSIP: Sequence Diagram AggiungiContattoOut Fig.9 GOSSIP: Sequence Diagram Logout Architettura del sistema Fig.10 GOSSIP: L’Architettura L’architettura implementa i servizi offerti da GOSSIP sfruttando sia il modello client/server che quello P2P. Comprende un BootStrapServer, un insieme di MessageServers ed un insieme di Servlets associati agli utenti del sistema (in ambito P2P un servlet è un' entità che usufruisce di servizi ed allo stesso tempo offre servizi). La Fig. 10 mostra uno schema generale dell'architettura. Presenta due Peer un BootStrapServer e due MessageServer, naturalmente il numero dei Peer e dei MessageServer è a scopo puramente esemplificativo. Il BootStrapServer fornisce il servizio di registrazione iniziale degli utenti, di connessione e di sconnessione dal sistema. Le funzioni dei vari componenti dell’Architettura sono già state spiegate precedentemente. Diamo una breve descrizione dell’uso dei protocolli effettuato in GOSSIP. Il Protocollo RMI viene usato nel collegamento tra un Peer ed il BootStrapServer, la comunicazione tra i due peer viene permessa tramite il protocollo TCP, mentre inizialmente (durante il Login dell’utente) il BootStrapServer chiede ad ogni message server, in MULTICAST, quante righe contiene il loro file, ed ognuno a sua volta risponde, in MULTICAST, inviando il proprio numero di righe. Questa scelta permette la minimizzazione del carico dei MessageServer. Successivamente, il BootStrapServer invia (tramite il protocollo UDP) al MessageServer che contiene il numero minore di righe, le informazioni sul Peer. Il MessageServer scelto, chiede in MULTICAST agli altri se hanno messaggi riguardante quel client, chi li possiede, risponde inviando (sul collegamento MULTICAST) un pacchetto contenente tutti i messaggi per il dato utente. Dopodichè, al momento dell’avvenuta connessione del Peer, il MessageServer gli spedisce (tramite UDP) tutti i messaggi. Dislocazione dei componenti Fig.11 GOSSIP: Vista Ibrida La figura, rappresenta una Vista Ibrida, mostra componenti e connettori, con lo scopo di evidenziare la dislocazione dei componenti sui vari nodi, e il tipo di comunicazione adottata. Nella figura è mostrato solo un esempio di quello che può essere l’architettura, in quanto gli oggetti sono in forma istanza quindi non rappresentano situazioni generali, ma situazioni particolari. Guida per l’amministratore di rete Funzionalità e servizi del BootStrapServer e dei MessageServer Il progetto si compone di due parti fondamentali per il giusto funzionamento di tutti i servizi. Esse sono l’avvio del BootStrapServer e del MessageServer. Senza il BootStrapServer, in pratica, per l’utente è come se non fosse disponibile nessun servizio e sarebbe impossibile per lui “chattare” con i suoi amici. Senza il MessageServer, inoltre, l’utente è impossibilitato a utilizzare il servizio di posta elettronica per gli utenti fuori linea, quindi è bene assicurarsi che sia BootStrapServer che MessageServer siano attivi, anche sulla stessa macchina, naturalmente si consiglia di dislocarli su due macchine diverse in modo tale da avere più risorse hardware disponibili. È consigliabile anche attivare vari MessageServer su più macchine. Attivare un MessageServer su una sola macchina non porterebbe a nulla di buono in quanto andrebbero ad utilizzare le stesse porte e di conseguenza lancerebbero eccezioni di diversa natura. L’architettura generale per l’interazione Client-BootStrapServer è basata sulle RPC (Remote Procedure Call), questo vuol dire che il Client invoca una procedura RPC definita sul server. L’invocazione della procedura avviene sull’host su cui è in esecuzione il client ma la procedura viene eseguita sull’host su cui è in esecuzione il server. Il server definisce l’oggetto remoto (BootStrapServer, nel nostro caso), cioè, definisce un oggetto distribuito (un oggetto i cui metodi possono essere invocati da parte di processi in esecuzione su hosts remoti), server nel nostro caso, dopodichè crea un legame tra il “nome simbolico di un oggetto ed il riferimento a quell’oggetto” (nel nostro caso: “BootStrapServer / server”) e lo pubblica mediante un servizio di tipo registry. Quando il client vuole accedere all’oggetto remoto (per esempio quando un utente vuole fare la registrazione o il login ecc.) per prima cosa ricerca un riferimento all’oggetto remoto mediante i servizi offerti dal registry, dopo di che invoca i metodi definiti dall’oggetto remoto (RMI remote method invocation). Da questo l’importanza di attivare il server che fornisce il servizio di registrazione di oggetti remoti (registry) prima di aver avviato il BootStrapServer. Al suo interno il BootStrapServer utilizza un metodo della classe Naming (contente i metodi per la gestione dei registry), il rebind(), che crea un collegamento tra un nome simbolico (qualsiasi) ed un riferimento all’oggetto. Se esiste già un collegamento per lo stesso oggetto all’interno dello stesso registry, tale collegamento viene sovrascritto. Attivazione del registry RMI L’attivazione del registry in background si esegue scrivendo la seguente riga: $> rmiregistry & Per default, viene creato un registry alla porta 1099, se la porta è già utilizzata viene sollevata una eccezione, per scegliere esplicitamente una porta si digita il comando $> rmiregistry numeroporta & Il client a sua volta, ricerca un riferimento all’oggetto remoto e invoca i metodi dell’oggetto remoto come fossero metodi locali con l’unica differenza di intercettare RemoteException che potrebbe essere lanciata da uno qualsiasi dei metodi remoti. Per ricercare un riferimento all’oggetto remoto, il client deve accedere al registry effettuando il Naming.lookup(registryURL) dove registryURL è una stringa formata in questo modo: rmi://hostName:portNum/BootStrapServer" e hostName e portNum rappresentano, rispettivamente, il nome dell’host su cui si trova il BootStrapServer e la porta su cui è attivato il registry. Il riferimento restituito dal registry è un riferimento ad un oggetto di tipo Object, esso viene castato al tipo definito nell’interfaccia remota (BootStrapServerInterface). Nello sviluppo del progetto abbiamo preferito utilizzare RMI sia per l’invocazione client-server (registrazione, login ecc.) che per quella server-client (notifyMe notifica del verificarsi di un evento) utilizzando il meccanismo delle callback. In questo modo oltre al server anche il client definisce un’interfaccia remota (ClientInterface) che definisce i metodi remoti utilizzati dal server per notificare un evento al client. Il BootStrapServer ha a disposizione ClientInterface e il Client ha a disposizione il BootStrapServerInterface. Il Client però non registra l’oggetto remoto in un rmiregistry, ma passa un riferimento a tale oggetto al BootStrapServer. Attivazione MessageServer & BootStrapServer Il MessageServer a sua volta deve essere avviato aggiungendo alla riga di comando una stringa che rappresenta il nome del file su cui si vuole creare la struttura di salvataggio dei messaggi. Il comando $> java MessageServer nomefile.txt lancia un message server e crea un file di nome prova.txt dove, al momento opportuno andrà ad effettuare operazioni di lettura o di scrittura, a seconda della situazione in cui ci si trova. Qualora si dimenticasse di associare il file nella riga di comando, viene lanciata un’eccezione che avvisa l’amministratore della dimenticanza avvenuta. Il BootStrapServer si attiva con il comando $> java BootStrapServer Guida per l’utente Generico Passi principali: Prima di usufruire del servizio, devi effettuare una registrazione in cui fornisci al sistema il tuo nickname e l'indirizzo IP. Il sistema verifica che il nickname non sia stato già scelto da altri utenti ed, in caso affermativo, registra i tuoi dati in un proprio database. Successivamente, puoi usufruire del servizio connettendoti al sistema (login) e quindi disconnettendoti dal sistema (logout). Ogni utente è caratterizzato da uno stato di presenza sulla rete che indica, in ogni istante, se esso è online, cioè ha effettuato il login, oppure offline. Ogni utente definisce una propria Lista di Contatti di Ingresso, in cui inserisce i nicknames di tutti i mittenti dai quali è disposto a ricevere messaggi ed una lista di Lista di Contatti di Uscita che contiene i nicknames di tutti gli utenti a cui intende inviare i messaggi. Prima di inserire un nuovo contatto C nelle propria lista, l' utente invia il nickname di C a GOSSIP, che verifica l'esistenza di un utente con quel nickname. Puoi inserire un utente U nella tua lista dei Contatti di Uscita solo se U ti ha preventivamente inserito nella propria Lista di Contatti di Ingresso. Quando sei in linea, in ogni momento, conosci lo stato di presenza degli utenti presenti nella tua Lista di Contatti di Uscita, viene aggiunto un “+” davanti al nickname dell’utente, se è connesso, altrimenti rimane scritto solo il nickname. Nel caso in cui un utente U modifichi il proprio stato, il sistema notifica tale cambiamento a tutti gli utenti interessati. Per esempio, se U è presente nella tua Lista di Contatti di Uscita e sta effettuando il Login, a connessione avvenuta, davanti al suo nome verrà aggiunto il simbolo “+”, questo per indicare che in quel momento U è in linea. Dopo esserti connesso al sistema, puoi inviare messaggi ad un qualsiasi altro utente U contenuto nella tua Lista dei Contatti di Uscita. Nel caso in cui il destinatario del messaggio sia online il messaggio gli viene recapitato in tempo reale, altrimenti il sistema memorizza il messaggio e lo recapita al destinatario al momento della sua successiva connessione al sistema. GOSSIP realizza quindi un servizio di Instant Messaging per gli utenti in linea ed un servizio simile alla Posta Elettronica per gli utenti fuori linea. Avvio del Client Per avviare l’interfaccia grafica che ti permette di gestire queste interazioni, devi come prima cosa compilare il codice, utilizzando Eclipse oppure digitando da shell il comando $> javac “pathname/nomefile.java” Genererà un nomefile.class che sarà mandato in esecuzione con il comando $> java “pathname/nomefile” Presentazione dell’interfaccia: L’interfaccia si presenta in questo modo: Inizialmente i pulsanti abilitati sono solamente Registrazione e Login, in quanto nessun altra operazione si può effettuare se non si è prima connessi al sistema. A Login effettuato, comparirà la possibilità di premere Logout, ParlaCon, e i due pulsanti +. Accanto alla scritta Nickname naturalmente andrà inserito il nickname scelto, ed accanto alla scritta Server andrà scritto il nome dell’host su cui si trova il BootStrapServer (vedere sezione Guida per l’amministratore di Rete). Il tutto è abbellito da una simpatica nuvoletta dove verranno notificate tutte le informazioni riguardo le funzioni disponibili. “Logout” serve per effettuare la disconnessione dal sistema. “Parla con” viene usato per parlare istantaneamente con un amico o per mandare messaggi offline, servizio simile alla posta elettronica I pulsanti “+” consentono di inserire nuovi contatti (in ingresso o in uscita rispettivamente) nella finestra in cui si trovano, gli effetti sono stati spiegati precedentemente Sviluppi futuri: prendiamo innanzi tutto in esame l’interfaccia grafica, in futuro è pensabile di migliorarla e renderla più userfriendly. Esaminando i servizi RMI, vediamo che è facile pensare di implementarne altri permettendo, per esempio ad un utente di fare delle comunicazioni in conferenza o di fare ricerche su tutti i contatti in linea. Spostandoci sull’implementazione da noi adottata, si rileva la totale mancanza di sicurezza nella comunicazione tra due utenti. Inoltre manca anche la possibilità di inserire insieme al proprio nickname, una password durante la registrazione, impedendo così l’accesso agli utenti non registrati (Es: se un utente proprietario di un nick è assente, nessun altro può accedere con lo stesso nome). E’ possibile implementare il trasferimento di file, oltre alla chat, permettendo agli utenti registrati di scambiarsi file di diverso tipo oltre allo scambio di informazioni in forma testuale. Naturalmente a nostro vantaggio, per l’espansione del progetto, abbiamo la possibilità di metterlo in rete con licenza opensource-GPL, cosicché ogni utente può apportare migliorie al progetto dove le ritenga necessarie. Bibliografia Lucidi visti a lezione durante il corso di Laboratorio Programmazione di Rete, tenuto dalla prof. Laura Ricci supportata dal prof. Paolo Mori, dell’anno scolastico 2006/2007 J. Arlow, I. Neustadt, UML 2 e Unified Process, Seconda Edizione italiana, McGraw-Hill, 2006 O.Reilly, Java Network Programming 2 Si ringraziano le professoresse Laura Ricci e Laura Semini per la loro disponibilità.