I problemi che devono essere affrontati nella realizzazione di programmi la cui esecuzione viene effettuata all'interno di un sistema a risorse distribuite presentano caratteristiche peculiari che si possono riassumere nell'identificazione e localizzazione delle risorse necessarie per la sua effettiva esecuzione.
Si tenga presente che, in molti casi, il programma è parallelo a tutti gli effetti, nel senso che l'esecuzione è ottenuta lanciando le sue componenti sequenziali su uno o più nodi della rete ed, inoltre, deve essere stato previsto uno specifico protocollo per lo scambio di informazioni fra le varie componenti sequenziali.
Si rammenta, a questo proposito, che tali componenti hanno la struttura tipica dei server, ossia, sono programmi continuamente attivi sulla rete perchè contribuiscono a fornire i servizi cui il programma parallelo è destinato. Nel caso più semplice lo schema è quello di un unico programma server che fornisce un certo servizio mentre è in esecuzione su nodo noto della rete a tutti i processi clienti che ne fanno richiesta.
Lo schema multi-client/single-server in modalità connessa è il
più semplice da realizzare. La figura riportata di seguito
Schema client-server
ne illustra chiaramente la struttura. La realizzazione è quella
standard per la rete Internet.
L'implementazione mediante socket è quella che si può
dedurre nel caso esemplificato del servizio fornito da un certo
server, che è quello di
listare il contenuto di un
direttorio, passato come parametro, della macchina su cui il server
è in esecuzione.
Il cliente chiederà
al server di listare il contenuto di un direttorio ed è stato
realizzato per connettersi su una specifica macchina oppure su quella
passata come parametro nella fase di inizio di esecuzione del cliente.
Per compilare i due programmi è necessario eseguire i comandi
A questo punto lanciare l'esecuzione col comando
Si noti nel codice del server la presenza della chiamata setsockopt
con lo scopo di definire opportunamente alcune opzioni nella gestione
della socket. Nel caso specifico i parametri passati servono a permettere
il riutilizzo dell'indirizzo assegnato dalla bind per chiamate
successive del server.
Come &grave facile rendersi conto il server termina normalmente dopo aver
accettato la prima richiesta. In generale, tuttavia, i server devono essere
realizzati in modo da poter rispondere ad un numero qualsivoglia di richieste
provenienti dai clienti. Il secondo tipo di server soddisfa questa richiesta, nel senso
che rimane sempre attivo in attesa di essere risvegliato da qualche cliente.
Per lanciare l'esecuzione di questa versione modificata di server si eseguano
i comandi riportati di seguito sulla macchina prescelta per il server
Si noti, nel codice di mserver.c,
la presenza dell'istruzione signal che ha il compito di modificare
la maschera delle interruzioni per il processo in modo che questo ignori
il segnale di terminazione dei processi figli i quali, altrimenti, darebbero
luogo a processi zombie.
gcc -lnsl -lsocket -o client client.c
gcc -lnsl -lsocket -o server server.c readdir.c
e trasferire l'eseguibile server sulla macchina scelta, secondo
quanto indicato nella variabile HOST del client.
server &
gcc -lnsl -lsocket -o mserver readdir.c mserver.c
mserver &
e quindi lanciare i clienti remotamente, verificando che questi tentino
la connessione sul nodo corretto. Ricordarsi di uccidere il processo
mserver. Si consideri anche il caso di lanciare più server
sulla stessa macchina o su macchine diverse e si cerchi di capire le
eventuali modifiche da apportare al codice.