Progetto Client Chat

Antonio D'Errico 2148054262

 

 

Corso di Reti di Calcolatori
Prof. Antonio Corradi
Università di Bologna Facoltà di Ingegneria

 

 


Realizzazione di un client per una chat aziendale
2 - Analisi dei requisiti e specifica del progetto



I-Architettura del sistema

 Il sistema e' basato sul pattern Client Server. Il client si connettera' al server utilizzando una socket di tipo Stream e dopo la fase di autenticazione iniziale potra' iniziare a raccogliere le seguenti informazioni dal server:
- clienti connessi,
- gruppi attivi,
- messaggi utente,
ed interagire con gli altri utenti.
Il client ha il compito di mostrare all'utente tutti i gruppi disponibili, il gruppo correntemente selezionato, l'indirizzo Ip del server al quale sono connesso e tutti gli utenti con i quali puo' scambiare messaggi e che sono attualmente connessi a quel gruppo.

 

 

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.
Client e server si scambiano messaggi che fanno parte del protocollo, tali messaggi traducono le azioni utente e non sono altro che stringhe di testo che vengono scambiate ed interpretate dalle due diverse controparti.
Il server in particolare invia al client un messaggio di azione andata a buon fine o azione abortita a seconda dell'azione richiesta e dell'esito che questa ha avuto. Il client dal canto suo puo' mantenere una coda pendente di 10 messaggi senza averne ricevuta conferma di esecuzione da parte del server. Il server inoltre invia in modo automatico messaggi verso il client in modo da informarlo sulla dinamicita' dei cambiamenti di stato dei gruppi, degli utenti e, caso questo piu' frequente, sui messaggi che vengono inviati dagli altri client connessi al gruppo.
Esiste attualmente una limitazione che riguarda il numero di gruppi ai quali un client puo' essere contemporanemente connesso e tale limite e' fissato ad 1. Tale limitazione ha solo una piccola ragione pratica che riguarda la complessita' dell'interfaccia grafica che avrebbe appesantito il sistema, in quanto avrei dovuto aprire piu' finestre per gestire i messaggi inoltre l'utente dovrebbe seguire piu' discussioni contemporaneamente e lavorare quindi a diversi progetti
.

 




II-Messaggi

 II.a-Messaggi Client/Server


  Il client ed il server si scambiamo messaggi in forma di stringa e generalmente hanno il seguente formato:

<Header> <Info Message>


Dove <Header> appartiene all'insieme descritto nella seguente tabella:

 

USER

username invia un messaggio per comunicare l'username (fase di autenticazione);

PASS

password invia un messaggio per comunicara la password (fase di autenticazione);

MSG

testo del messaggio invia un messaggio a tutti gli utenti del gruppo;

PMSG

utente@gruppo@testo del messaggio invia un messaggio privato all'utente di quel gruppo (non implementato);

LISTGROUPS

nel caso di interfaccia caratteri posso richiedere la lista dei gruppi in qualsiasi momento e non solo quando questa viene aggiornata dal server;

LISTUSERS

nel caso di interfaccia caratteri posso richiedere la lista degli utenti in qualsiasi momento e non solo quando questa viene aggiornata dal server;

JOIN

gruppo mi permette di lasciare il gruppo corrente per inserirmi in un nuovo gruppo;

QUIT

abbandono soft della partecipazione (abbandono deciso dall'utente);

ERROR

messaggio di errore generico mandato al server;

 

 


 II.b-Messaggi Server/Client

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:

 

Cod. Messaggio

Formato

610

<Group_name_1> <Group_name_2>

 ...

<Group_name_n>

611

<User_name>:<IP_address>:<Port>

<User_name>:<IP_address>:<Port> 

612

<Group_name_1> <Group_name_2>

 ...

<Group_name_n>

632

<User_name>:<IP_address>:<Port>

<User_name>:<IP_address>:<Port>

 

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.




III-Cenni sull’implementazione

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.




IV-Funzionalita' non implementate

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.


 

Introduzione

Specifica requisiti

Specifica progetto

Java Doc

Sorgenti