Indice - Progetto di Reti di Calcolatori - Fabio Adani e Marco Chiesi
Analisi

Visione globale del sistema

L'architettura ad 'alto livello' dell'ambiente NetGame è rappresentata nella seguente figura.

Si possono distinguere tre componenti separati :

  • Server di Utenti
  • Server di NetGame
  • Client di NetGame

Server di Utenti.

Il Server di Utenti ha il compito di mantenere la lista degli utenti ammessi al sistema, ognuno con la rispettiva password di accesso. Esso è unico all'interno del sistema, anche se per ovvi motivi di availability e reliability può essere internamente replicato.

Server di NetGame

I Servers di NetGame sono generalmente più di uno e si coordinano per offrire il servizio distribuito ai clienti. Un obiettivo primario di questo coordinamento è rendere trasparente questa struttura ai clienti. Ogni server ha nozione di tutti gli altri e quindi può comunicare direttamente con ciascuno di essi.
I compiti di un server NetGame possono così essere riassunti :

  • Accettare connessioni da parte dei clienti, previa verifica dell'autorizzazione di accesso ottenuta consultando il Server di Utenti.
  • Gestire un certo numero di stanze da gioco.
  • Comunicare con gli altri servers per mantenere una visione coordinata e congrua dello stato del sistema.

Ogni Server NetGame può gestire più giochi, che dovranno essere sviluppati con un'opportuna struttura per poter essere inseriti all'interno del framework. Ad ogni gioco viene riservata una stanza. Una stanza rappresenta un ambiente in cui utenti interessati al medesimo gioco possono incontrarsi, chattare, organizzare partite e giocarle. Vi è una corrispondenza biunivoca all'interno di un server tra giochi e stanze che li ospitano.
La decisione di quali stanze debbano essere preparate viene effettuata all'avvio del server. Tralasciando per ora i dettagli (che verranno poi trattati nella fase di progetto ed implementazione) un server valuterà all'avvio quali giochi compatibili NetGame sono disponibili sulla propria macchina e per ciascuno di essi creerà una stanza opportuna. Non è quindi necessario che tutti i Server del sistema gestiscano gli stessi giochi: una stanza si metterà in contatto unicamente con le stanze analoghe (cioè che ospitano lo stesso gioco con la stessa versione) sui servers remoti.

L'ingresso di un server in un sistema può avvenire in due modi :

  • Creando una nuova rete. In questo caso tale server sarà il primo della rete, lo stato iniziale sarà completamente vuoto (nessun utente connesso) e fintanto che nessun altro server farà ingresso nella rete non ci sarà bisogno di coordinarsi con esso e gli utenti saranno solo locali.
  • Introducendosi in una rete già attiva. In questo caso il server dovrà contattare uno qualsiasi dei servers della rete e richiedere di entrare a farne parte. In caso di successo il nuovo server dovrà ricevere lo stato aggiornato del sistema : utenti connessi e stato di ogni singola stanza (con utenti nella stanza, partite in definizione, in esecuzione, ecc). In questa fase ogni stanza sarà messa in contatto con tutte le analoghe su tutti i server facenti parte della rete.

Un server può entrare ed uscire in qualsiasi momento in una rete. Si è cercato quindi di ottenere una buona dinamicità. All'atto dell'uscita tutti i clients gestiti da lui saranno però forzatamente disconnessi dal sistema e se vorranno rientrare dovranno rivolgersi ad un alto server (magari più affidabile...)
Questo avviene perchè ogni server è responsabile in toto dei propri utenti locali e mantiene, per gli utenti remoti, solo le informazioni minime per garantire consistenza dello stato. Lo stato complessivo del sistema è quindi distribuito. La comunicazione avviene preferibilmente inter-server e la comunicazione con un client avviene direttamente solo da parte del server a cui quel client è connesso.

Una volta iniziata una partita il suo stato viene accentrato e se ne occupa la stanza del giocatore che l’ha iniziata. Ogni gioco potrà gestire autonomamente il pattern di comunicazione tra i clienti e con il server, scegliendo quello più opportuno. L'unica cosa che gli si chiede è di soddisfare opportuni vincoli (in particolare, come si vedrà,  di struttura di classi e di implementazioni di interfacce) per poter essere adeguatamente ospitato dentro l'infrastruttura NetGame.

Client di NetGame

I clients di NetGame rappresentano gli utenti. Tipicamente un utente per accedere a NetGame dovrà innanzitutto disporre di un account registrato e conoscere l'indirizzo di un server facente parte di una rete attiva. Soddisfacendo questi due requisiti, il client potrà connettersi a tale server, ed in modo del tutto trasparente entrare in contatto con tutti gli altri utenti connessi ad altri server della stessa rete.
Una volta connesso l'utente potrà entrare in una stanza di gioco, sempre che :

  1. Tale stanza sia presente sul server (il che comporta che il server abbia la parte server dell’implementazione di quel gioco)
  2. Il client disponga della parte client dell’implementazione del gioco.

Analogamente a quanto avviene per i server, anche i client cercano dinamicamente i giochi compatibili NetGame presenti sulla macchina locale all'avvio. E' però possibile anche scaricarli dal server nel caso non siano disponibili localmente. Una volta scaricati, saranno anche posti all'interno del file system locale di modo da essere riconosciuti successivamente. Sarà quindi necessario scaricare ogni gioco al più una volta.

Una volta entrato in una stanza di gioco un giocatore potrà compiere le seguenti operazioni :

  • mandare un messaggio pubblico visibile a tutti gli utenti nella stanza
  • mandare un messaggio privato ad un unico utente della stanza
  • creare una partita
  • uscire da una partita
  • entrare in una partita
  • iniziare una partita

Contemporaneamente sarà informato di ciascuna azione di questo tipo compiuta dagli altri utenti.
Naturalmente le operazioni di cui sopra sono possibili se sono verificate opportune condizioni. In particolare ogni gioco di NetGame ha un numero massimo ed un numero minimo di giocatori consentiti per ogni partita. Di conseguenza un giocatore potrà entrare in una partita solo se il suo ingresso non comporta la presenza di un numero di giocatori maggiore di quello previsto. Analogamente un giocatore può iniziare una partita solo se ad essa si sono iscritti già abbastanza giocatori. Inoltre l'inizio della partita è consentito solo al creatore della partita o comunque al primo giocatore iscritto (nel caso che il creatore se ne sia uscito). Nel caso un giocatore esca da una partita in cui è l'unico iscritto, la partita viene automaticamente eliminata.

Ogni giocatore può essere iscritto o giocare ad una sola partita in ogni momento. Una volta che una partita inizia, viene caricata l'interfaccia grafica del gioco e l'utente interagisce con essa. L'interfaccia grafica del client NetGame viene comunque tenuta attiva, per permettere al giocatore di scambiare messaggi con gli altri utenti della stanza ed in particolare con gli avversari.

Tematiche affrontate

La realizzazione del presente progetto ci consentirà di affrontare le seguenti tematiche :

  • Utilizzo del linguaggio di programmazione Java ed in particolare delle API messe a disposizione da tale framework  per operare in un ambiente distribuito. Particolare attenzione sarà posta all'uso delle RMI (Remot Method Invocation) di Java, in quanto tutta la comunicazione (sia inter-server che tra client e server) verrà  implementata con tale modello. Di tale API sarà quindi possibile apprezzare sia pregi che difetti.
    L'uso di Java consentirà di affrontare con un'ottica object-oriented tutto lo sviluppo dell'applicazione, a partire dall'analisi sino all'implementazione e alla codifica. Inoltre permetterà di trarre tutti i vantaggi dell'OOP, quali la modularità e la riusabilità del codice.
  • Coordinamento di più server peer-to-peer per mantenere una visione consistente dello stato del sistema. La presenza di più server coordinati nel modo sopra spiegato e la presenza di uno stato distribuito introdurrà problemi di sincronizzazione. E' evidente infatti che ci sono operazioni che, se compiute contemporaneamente e senza alcun controllo su server diversi, potrebbero portare ad una inconsistenza complessiva dello stato del sistema. Si pensi ad esempio al caso in cui un giocatore cerca di iniziare una partita mentre un altro cerca di uscirne, magari portando il numero di giocatori iscritti ad un numero inferiore a quello previsto per quel gioco.
  • Tecniche per disaccoppiare client e server durante le chiamate remote. Le chiamate remote sono tipicamente sincrone, e questo è anche il caso delle RMI di Java. Alcuni requisiti di questo progetto però si scontrano con questo vincolo. In particolare si vuole che le elaborazioni locali (si pensi anche all'aggiornamento dell'interfaccia grafica) dalla parte del client procedano senza necessariamente aspettare che la chiamata remota, che come vedremo potrà essere anche molto costosa, termini. Questo dovrà avvenire comunque mantenendo i vincoli imposti dal precedente punto. In sostanza vogliamo delle chiamate remote sincrone ma non bloccanti.
    Inoltre vogliamo che i server comunichino in parallelo e non in modo sequenziale con tutti gli altri server con cui sono connessi.
  • Punti cruciali di questo progetto sono l'estendibilità e la modularità. Questi concetti sono pervasivi e si applicano a diversi aspetti del progetto. Si pensi alla gestione dei giochi, con la possibilità di inserirne facilmente di nuovi e di scaricarli da parte del server. Si pensi alla possibilità di ospitare giochi strutturati anche molto diversamente gli uni dagli altri. Si pensi alla possibilità da parte dei server di connettersi e disconnettersi dal sistema in un qualunque momento, senza che il suo funzionamento venga alterato. Una spinta decisiva verso questa direzione è data dal linguaggio java stesso e dall'uso delle RMI, che impongono una formalizzazione non ambigua delle interfacce remote che può fornire un oggetto server. Ogni componente del sistema è rintracciabile attraverso una ben specifica interfaccia. Si pensi all'esempio del Server di utenti: la sua implementazione sarà del tutto oscura al resto del sistema. Potrà essere implementato come una banalissima applicazione che opera su un file di testo o come un sofisticato DBMS. Questa metodologia evidentemente apre anche orizzonti per eventuali miglioramenti.

Ipotesi di Guasto

Il sistema deve essere in grado di fare fronte alla caduta di uno o più servers e/o clients. In particolare

  • In caso di caduta di un server, gli altri servers provvedono a chiudere la connessione ad esso.
  • In caso di caduta di un client, il server a cui è connesso provvede ad avvisare tutti gli altri servers della sua disconnessione.
  • In caso di caduta di un server di utenti, i server che si appoggiano ad esso per l’autenticazione dei clients, non potranno accettare nuove connessioni finché il collegamento non sarà ricostituito.

Si assume inoltre l'ipotesi semplificativa che NON si verifichino partizionamenti nella rete. Nel caso in cui ciò dovesse accadere, non sarà possibile riconnettere le due sottoreti, ma semplicemente ognuna di esse continuerà la sua attività in modo indipendente dall'altra.
In caso di caduta di un server inoltre i clients ad esso connessi verranno esclusi dal sistema e gli altri server provvederanno a cancellare la loro presenza, eventualmente agendo anche a livello di stanze e di partite iniziate.

Indietro Inizio pagina Avanti
Indice   Fabio Adani e Marco Chiesi