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 :
- Tale stanza sia presente sul server (il
che comporta che il server abbia la parte server dell’implementazione
di quel gioco)
- 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.
|