Progetto Client Chat Antonio D'Errico
2148054262 |
|
Corso di Reti
di Calcolatori |
|||||||||||||||||||||||||||||||||
|
Realizzazione di un client
per una chat aziendale
I server suddividono i client connessi, in insiemi
che sono denominati gruppi. Ogni gruppo, che ha un nome specifico, puo' avere
da 0 a N client connessi. I gruppi sono nati con l'intenzione di suddividere
tutti gli utenti connessi nell'ambito aziendale, in base ad aree di interesse
particolari ed evitare che messaggi relativi a progetti diversi si mescolino.
Ogni utente per ora puo' liberamente richiedere la lista dei gruppi e passare
da un gruppo ad un altro. Il cliente appena connesso viene automaticamente
inserito in un gruppo che esiste sempre ed e' chiamato default.
<Header> <Info
Message>
201: Ok con inserimento
al gruppo; 202: Ok con rimozione dal
gruppo; 203: Ok login
effettuato; 241: Ok messaggio
pubblico consegnato; 242: Ok messaggio
privato consegnato; 310: Successo parziale
nel login; 430: Fail, fase di
autenticazione; 441: Fail, errore nella
consegna del messaggio pubblico; 442: Fail, errore nella
consegna del messaggio privato; 610: Risposta al comando
LISTGROUPS; 611: Messaggio
automatico di refresh della users window; 612: Messaggio
automatico di refresh della groups window; 632: Risposta al comando
LISTUSERS; 641: Messaggio pubblico da
un utente del gruppo; 642: Messaggio privato
da un utente del gruppo; Di questi messaggi di
risposta alcuni hanno un formato più complesso in quanto riportano delle
rappresentazioni di strutture dati che devono essere fornite all’utente tali
messaggi sono:
Il formato di risposta è
fondamentalmente lo stesso per 610/612 e 611/632 ma cambia ovviamente il modo
di elaborazione da parte del client in quanto risponde messaggi differenti. Se il client, cessa di
esistere o invia il messaggio di QUIT, è automaticamente rimosso da tutte le
strutture dati che il server gestisce ed è considerato disconnesso, tutti i
client del gruppo di appartenenza del client rimosso, ricevono la nuova lista
utenti.
Nel progetto si fa uso dell’introspezione che Java fornisce per le sue classi. Essendo questo un classico progetto nel quale bisogna elaborare dei messaggi inviati da un’entità ad un’altra e desumere dall’header del messaggio l’informazione in esso contenuta si è scelto di utilizzare l’introspezione e l’invocazione dinamica dei metodi invece di strutturare il tutto in un gigantesco switch (cosa possibile in questo caso visto che l’header è numerico, ma non molto comoda visto che il codice può esplodere in modo che non possa essere facilmente controllato). I punti che ho seguito per utilizzare
l’introspezione sono i seguenti: -
per ogni comando ho creato un metodo il cui
nome è derivabile direttamente dal header numerico del messaggio; -
ho un oggetto Method che rispecchia il
metodo che dovrà essere usato per processare il comando; -
invoco dinamicamente il metodo ottenuto
rappresentato dall’oggetto Method passandogli gli argomenti appropriati. La chiave di tutto è proprio l’invocazione
dinamica dei metodi. Per primo
bisogna determinare la classe dell’oggetto che contiene il metodo che voglio
invocare, il problema viene risolto dal metodo getClass() che ritorna un
oggetto di tipo Class che rappresenta la classe del mio oggetto run-time. Una
volta che conosco il nome della classe mi sincero che il metodo che mi serve
esista e me lo procuro (possono esserci più metodi con lo stesso nome ma che
hanno signature differenti). Anche questo problema mi viene risolto dal
metodo getMethod() che mi permette di scoprire se la classe contiene il
metodo e accetta due argomenti: -
un oggetto di tipo String che contiene il
nome del metodo in questione -
un array di oggetti di tipo Class che
identifica il tipo dei parametri
formali che il metodo accetta. getMethod() ritorna un oggetto di tipo Method, che
rispecchia il metodo che combacia con quanto specificato nei due argomenti,
altrimenti genera un’eccezione di tipo NoSuchMethodException. Quando però possiedo l’oggetto che rispecchia il
metodo ricercato posso utilizzare il metodo invoke() che dinamicamente lo
invoca. Ho incapsulato l’invocazione dinamica della
procedura richiesta nella classe Invoker che contiene solo un metodo di
classe dynaCall() che riceve tre argomenti: -
l’oggetto che contiene il metodo che voglio
invocare; -
il nome del metodo; -
l’argomento che altro non è che il testo
del messaggio da processare. -
N.B. In questo caso ho perso di generalità avrei
dovuto incapsulare in un oggetto gli argomenti passo ai metodi da invocare ma
i metodi che sono contenuti nella classe StdProtocol ricevono solo stringhe.
Per evitare di rendere il progetto troppo complesso si è scelto di non implementare tutte le funzionalità che comunque sono state previste nella fase di progettazione (cfr. partecipazione contemporanea a più gruppi). Tra di queste c’è appunto la fase di autenticazione che come è stato descritto nella paragrafo IV della specifica del progetto Server è stata però prevista nel protocollo.
|