-Il server richiede (\texttt{\small 11}) che sia stata impostata una dimensione
-dell'insieme delle frasi non nulla, stampando, nel caso ciò non avvenga, un
-messaggio apposito ed uscendo. Poi (\texttt{\small 12}) effettua la chiamata
-alla funzione \code{FortuneParse} che legge dal file specificato in
-\var{fortunefilename} le prime \var{n} frasi e le memorizza nel vettore di
-puntatori \var{fortune}. Il codice della funzione non è riportato, in quanto
-non direttamente attinente allo scopo dell'esempio, lo si può trovare nel file
-\file{FortuneParse.c} allegato coi sorgenti degli esempi.
-
-Il passo successivo \texttt{\small 16--21}) è quello di creare, se non esiste
-già, la fifo nota sulla quale il server ascolterà le richieste, qualora si
-riscontri un errore il server uscirà (escludendo ovviamente il caso in cui la
-funzione \func{mkfifo} fallisce per la precedente esistenza della fifo.
-
-Fatto questo si entra nel ciclo principale del programma \texttt{\small
- 22--36}), che viene eseguito indefinitamente (l'uscita del server deve
-essere effettuata tramite segnale), e che provvede a fornire le risposte ai
-client. Il server è progettato per accettare le richieste dai client che
-devono scrivere il nome della fifo sulla quale vogliono ricevere la risposta
-sulla fifo su cui il server è in ascolto.
-
-Il primo passo è aprire in lettura la fifo (\texttt{\small 23}), se nessun
-client ha effettuato una richiesta la fifo non ha capi aperti in scrittura, e
-pertanto il server si bloccherà. Una volta che un client ha aperto la fifo in
-scrittura il server si sbloccherà ed effetturà la lettura (\texttt{\small 28})
-della richiesta del client (nel caso limitata a 79 byte).
-
-Dopo di che verrà calcolato (\texttt{\small 30}) un numero casuale nel range
-delle frasi disponibili nella nostra lista, e verrà aperta (\texttt{\small
- 31}) la fifo sulla quale il client vuole ricevere la risposta, che sarà poi
-scritta (\texttt{\small 32}). Dopo di che \texttt{\small 34--35}) entrambe le
-fifo verranno chiuse.
+Il server richiede (\texttt{\small 12}) che sia stata impostata una dimensione
+dell'insieme delle frasi non nulla, dato che l'inizializzazione del vettore
+\var{fortune} avviene solo quando questa dimensione viene specificata, la
+presenza di un valore nullo provoca l'uscita dal programma attraverso la
+routine (non riportata) che ne stampa le modalità d'uso. Dopo di che installa
+(\texttt{\small 13--15}) la funzione che gestisce i segnali di interruzione
+(anche questa non è riportata in \figref{fig:ipc_fifo_server}) che si limita a
+rimuovere dal filesystem la fifo usata dal server per comunicare.
+
+Terminata l'inizializzazione (\texttt{\small 16}) si effettua la chiamata alla
+funzione \code{FortuneParse} che legge dal file specificato in
+\var{fortunefilename} le prime \var{n} frasi e le memorizza (allocando
+dinamicamente la memoria necessaria) nel vettore di puntatori \var{fortune}.
+Anche il codice della funzione non è riportato, in quanto non direttamente
+attinente allo scopo dell'esempio.
+
+Il passo successivo (\texttt{\small 17--22}) è quello di creare con
+\func{mkfifo} la fifo nota sulla quale il server ascolterà le richieste,
+qualora si riscontri un errore il server uscirà (escludendo ovviamente il caso
+in cui la funzione \func{mkfifo} fallisce per la precedente esistenza della
+fifo).
+
+Una volta che si è certi che la fifo di ascolto esiste si procede
+(\texttt{\small 23--32}) alla sua apertura. Questo viene fatto due volte
+per evitare di dover gestire all'interno del ciclo principale il caso in cui
+il server è in ascolto ma non ci sono client che effettuano richieste.
+Si ricordi infatti che quando una fifo è aperta solo dal capo in lettura,
+l'esecuzione di \func{read} ritorna con zero byte (si ha cioè una condizione
+di end-of-file).
+
+Nel nostro caso la prima apertura si bloccherà fintanto che un qualunque
+client non apre a sua volta la fifo nota in scrittura per effettuare la sua
+richiesta. Pertanto all'inizio non ci sono probelmi, il client però, una volta
+ricevuta la risposta, uscirà, chiudendo tutti i file aperti, compresa la fifo.
+A questo punto il server resta (se non ci sono altri client che stanno
+effettuando richieste) con la fifo chiusa sul lato in lettura e a questo punto
+\func{read} non si bloccherà in attesa di input, ma ritornerà in continuazione
+restituendo un end-of-file.\footnote{Si è usata questa tecnica per
+ compatibilità, Linux infatti supporta l'apertura delle fifo in
+ lettura/scrittura, per cui si sarebbe potuto effettuare una singola apertura
+ con \macro{O\_RDWR}, la doppia apertura comunque ha il vantaggio che non si
+ può scrivere per errore sul capo aperto in sola lettura.}
+
+Per questo motivo, dopo aver eseguito l'apertura in lettura (\texttt{\small
+ 24--28}),\footnote{di solito si effettua l'apertura del capo in lettura in
+ modalità non bloccante, per evitare il rischio di uno stallo (se nessuno
+ apre la fifo in scrittura il processo non ritornerà mai dalla \func{open})
+ che nel nostro caso non esiste, mentre è necessario potersi bloccare in
+ lettura in attesa di una richiesta.} si esegue una seconda apertura in
+scrittura (\texttt{\small 29--32}), scartando il relativo file descriptor che
+non sarà mai usato, ma lasciando la fifo comunque aperta anche in scrittura,
+cosicchè le successive possano bloccarsi.
+
+A questo punto si può entrare nel ciclo principale del programma che fornisce
+le risposte ai client (\texttt{\small 34--50}), che viene eseguito
+indefinitamente (l'uscita del server viene effettuata inviando un segnale, in
+modo da passare attraverso la routine di chiusura che cancella la fifo).
+
+Il server è progettato per accettare come richieste dai client delle stringhe
+che contengono il nome della fifo sulla quale deve essere inviata la risposta.
+Per cui prima (\texttt{\small 35--39}) si esegue la lettura dalla stringa di
+richiesta dalla fifo nota (che a questo punto si bloccherà tutte le volte che
+non ci sono richieste). Dopo di che, una volta terminata la stringa
+(\texttt{\small 40}) e selezionato (\texttt{\small 41}) un numero casuale per
+ricavare la frase da invaire, si procederà (\texttt{\small 42--46})
+all'apertura della fifo per la risposta, che \texttt{\small 47--48}) poi vi
+sarà scritta. Infine (\texttt{\small 49}) si chiude la fifo di risposta che
+non serve più.
+
+Il codice del client è invece riportato in \figref{fig:ipc_fifo_client}, anche
+in questo caso si è omessa la gestione delle opzioni e la funzione che stampa
+a video le informazioni di utilizzo ed esce, riportando solo la sezione
+principale del programma e le definizioni delle variabili. Il codice completo
+è nel file \file{FortuneClient.c} dei sorgenti allegati.
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15cm}
+ \begin{lstlisting}{}
+int main(int argc, char *argv[])
+{
+/* Variables definition */
+ int n = 0;
+ char *fortunefilename = "/tmp/fortune.fifo";
+ char line[80];
+ int fifo_server, fifo_client;
+ char fifoname[80];
+ int nread;
+ char buffer[PIPE_BUF];
+ ...
+ snprintf(fifoname, 80, "/tmp/fortune.%d", getpid()); /* compose name */
+ if (mkfifo(fifoname, 0622)) { /* open client fifo */
+ if (errno!=EEXIST) {
+ perror("Cannot create well known fifo");
+ exit(-1);
+ }
+ }
+ fifo_server = open(fortunefilename, O_WRONLY); /* open server fifo */
+ if (fifo_server < 0) {
+ perror("Cannot open well known fifo");
+ exit(-1);
+ }
+ nread = write(fifo_server, fifoname, strlen(fifoname)+1); /* write name */
+ close(fifo_server); /* close server fifo */
+ fifo_client = open(fifoname, O_RDONLY); /* open client fifo */
+ if (fifo_client < 0) {
+ perror("Cannot open well known fifo");
+ exit(-1);
+ }
+ nread = read(fifo_client, buffer, sizeof(buffer)); /* read answer */
+ printf("%s", buffer); /* print fortune */
+ close(fifo_client); /* close client */
+ close(fifo_server); /* close server */
+ unlink(fifoname); /* remove client fifo */
+}
+ \end{lstlisting}
+ \end{minipage}
+ \normalsize
+ \caption{Sezione principale del codice del client di \textit{fortunes}
+ basato sulle fifo.}
+ \label{fig:ipc_fifo_client}
+\end{figure}
+
+La prima istruzione (\texttt{\small 12}) compone il nome della fifo che dovrà
+essere utilizzata per ricevere la risposta dal server. Si usa il \acr{pid}
+del processo per essere sicuri di avere un nome univoco; dopo di che
+(\texttt{\small 13-18}) si procede alla creazione del relativo file, uscendo
+in caso di errore (a meno che il file non sia già presente sul filesystem).
+
+A questo punto il client può effettuare l'interrogazione del server, pe questo
+prima si apre la fifo nota (\texttt{\small 19--23}), e poi ci si scrive
+(\texttt{\small 24}) la stringa composta in precedenza, che contiene il nome
+della fifo da utilizzare per la risposta. Infine si richiude la fifo del
+server che a questo punto non serve più (\texttt{\small 25}).
+
+Inoltrata la richiesta si può passare alla lettura della risposta; anzitutto
+si apre (\texttt{\small 26--30}) la fifo appena creata, da cui si deve
+riceverla, dopodiché si effettua una lettura (\texttt{\small 31})
+nell'apposito buffer; si è supposto, come è ragionevole, che le frasi inviate
+dal server siano sempre di dimensioni inferiori a \macro{PIPE\_BUF},
+tralasciamo la gestione del caso in cui questo non è vero. Infine si stampa
+(\texttt{\small 32}) a video la risposta, si chiude (\texttt{\small 33}) la
+fifo e si cancella (\texttt{\small 34}) il relativo file.
+
+Si noti come la fifo per la risposta sia stata aperta solo dopo aver inviato
+la richiesta, se non si fosse fatto così si avrebbe avuto uno stallo, in
+quanto senza la richiesta, il server non avrebbe potuto aprirne il capo in
+scrittura e l'apertura si sarebbe bloccata indefinitamente.