Desidererei avere delucidazioni sui concetti di PROGRAMMAZIONE CLIENT e PROGRAMMAZIONE SERVER e sulle loro differenze fondamentali; magari – se possibile – con un esempio pratico (chiarificatore) in proposito. Se per motivi di spazio o di tempo la mia richiesta fosse troppo impegnativa, va bene anche una semplice definizione per entrambe.

Vedi anche: una precedente
risposta di Luca Fini
sull’argomento

La programmazione client/server è di fondamentale importanza soprattutto
in questo momento in cui la larghissima diffusione di Internet impone
una programmazione di questo tipo. Il concetto fondamentale è quello
della suddivisione delle funzioni tra diversi programmi, che possano
comunicare tra di loro con un mezzo qualsiasi.

Nella programmazione tradizionale (anche la Client/Server si potrebbe
definire tradizionale visto la sua decennale storia) o forse sarebbe
meglio definirla standalone, si definisce un programma autonomo che
può portare a termine il compito per cui è stato realizzato, semplicemente
partendo da dei dati registrati su disco o inseriti dall’utente.
In questa situazione le variabili in gioco sono molto limitate ed è
decisamente una tecnica affidabile per molti scopi offrendo anche una
notevole sicurezza dei dati sia in ingresso che in uscita, nessuno potrà
mai mettere il naso in quei dati.

D’altro canto impone delle notevoli limitazioni, dovute proprio alla
sua chiusura verso l’esterno. Si pensi ad un programma che elabora dati
metereologici per calcolare delle previsioni. Ci sarà bisogno di una
grossa quantità di dati provenienti da moltissime stazioni di rilevamento
di pressione, umidità, velocità del vento, ecc. e tutte queste stazioni
saranno distribuite su un vasto territorio. E’ impensabile far fare
il giro di tutte le stazioni da una persona che poi riporti i dati al
centro di calcolo dove un programma li analizzerà. Troppo tempo per
la rilevazione dei dati, e eccessive spese di trasporto.

Da esigenze simili nasce l’architettura software Client/Server,
in cui il programma standalone scompare o si trasforma in client e uno
o più server offrono i servizi necessari per l’intero processo.

Riprendendo l’esempio precedente si potrebbe pensare ad un piccolissimo
software, installato in ogni stazione di rilevamento che ogni x
minuti registri i dati ambientali, e una rete di interconnessione tra
tutte le stazioni e le macchine coinvolte. Il software delle stazioni
si presenterebbe sulla rete come un server che su richiesta offre le
informazioni rilevate in un certo intervallo di tempo. A questo punto
abbiamo il nostro programma che si comporterà da client verso tutti
i software delle stazioni, ai quali chiederà periodicamente le ultime
registrazioni.

E’ chiaro che in uno scenario di questo tipo i vantaggi sono notevoli
rispetto al precedente, ma la cosa che vorrei sottolineare è che l’architettura
non è così rigida come potrebbe sembrare, non a caso ho usato il termine
“comporta”, infatti la suddivisione tra client e server è solo logica
e un programma può essere client di un server e server rispetto
ad un altro programma. Per chiarire questo concetto pensiamo alla manutenzione
del sistema dell’esempio, invece di mandare periodicamente qualcuno
a verificare il buon funzionamento delle stazioni di rilevamento (tutte),
si potrebbe fare in modo che il nostro generatore di previsioni metereologiche
accetti richieste, sia di previsioni, che dell’elenco delle stazioni
danneggiate o sospette di malfunzionamenti.

Il nostro calcolatore per raccogliere i dati deve necessariamente collegarsi
alle stazioni, e ovviamente se non ci riesce o i dati spediti sono eccessivamente
dissimili da quelli delle stazioni circostanti è molto alta la
probabilità che ci siano dei guasti in quelle stazioni. Ecco che il
nostro client rispetto alle stazioni di rilevamento dati, si è trasformato
in un server per lo staff di manutenzione e per tutti quelli che vogliono
controllare le previsioni.

Ora veniamo all’esempio pratico (file Server.zip,
50 Kb)
, che in effetti non mi costa molta fatica avendolo preparato
per un corso circa un anno fa, ma che presuppone una certa conoscenza
del C/C++ e del protocollo FTP. Il programma non fa altro che aprire
una consolle per visualizzare l’output testuale, e mettersi in ascolto
sulla porta (vedi Socket e TCP/IP) 21 usata dal protocollo FTP. Ho deciso
di usare questa porta proprio per evitare la stesura del client, infatti
si può usare il client FTP standard presente su tutti i sistemi.

Essendo un server di esempio è volutamente semplice e imita solo i
veri server FTP, in altre parole accetta connessioni dai client, ma
qualsiasi cosa gli chiedano, dalla lista dei file di una directory allo
scaricamento di un file, risponde sempre con il codice 200 che in FTP
significa operazione terminata con successo.

In realtà il server nella sua semplicità è un buon esempio di programmazione
multithread, infatti può accettare più connessioni contemporaneamente
e per ognuna crea un thread che la gestisce.

Per testarlo basta lanciarlo e lanciando da “Prompt MS-DOS” o semplicemente
col pulsante Start cliccare Esegui…, il comando: “ftp localhost”.
In questo modo lanciamo l’eseguibile ftp.exe dicendogli di collegarsi
alla stessa macchina da cui viene lanciato (dove gira il server di esempio
che abbiamo lanciato). E’ possibile lanciare il client ftp piu volte
come descritto, e si può verificare nella finestra del server i thread
lanciati e quelli morti (quando ci si scollega con il comando “close”
o “bye” dal client ftp.exe).

I sorgenti e l’eseguibile preferisco non commentarli per non rendere
eccessivamente lunga la risposta con cose abbastanza noiose per la maggior
parte dei lettori.

Riporto l’esempio sia in C che in C++, ma la versione più comprensibile
è quella C. La programmazione multithread è un argomento correlato all’esempio,
e che dovrebbe essere conosciuta anche se superficialmente per
comprenderlo meglio.