+useremo una sola coda di messaggi, usando il tipo di messaggio per comunicare
+in maniera indipendente con client diversi.
+
+\begin{figure}[!bht]
+ \footnotesize \centering
+ \begin{minipage}[c]{15cm}
+ \begin{lstlisting}{}
+int msgid; /* Message queue identifier */
+int main(int argc, char *argv[])
+{
+/* Variables definition */
+ int i, n = 0;
+ char **fortune; /* array of fortune message string */
+ char *fortunefilename; /* fortune file name */
+ struct msgbuf_read { /* message struct to read request from clients */
+ long mtype; /* message type, must be 1 */
+ long pid; /* message data, must be the pid of the client */
+ } msg_read;
+ struct msgbuf_write { /* message struct to write result to clients */
+ long mtype; /* message type, will be the pid of the client*/
+ char mtext[MSGMAX]; /* message data, will be the fortune */
+ } msg_write;
+ key_t key; /* Message queue key */
+ int size; /* message size */
+ ...
+ Signal(SIGTERM, HandSIGTERM); /* set handlers for termination */
+ Signal(SIGINT, HandSIGTERM);
+ Signal(SIGQUIT, HandSIGTERM);
+ if (n==0) usage(); /* if no pool depth exit printing usage info */
+ i = FortuneParse(fortunefilename, fortune, n); /* parse phrases */
+ /* Create the queue */
+ key = ftok("./MQFortuneServer.c", 1);
+ msgid = msgget(key, IPC_CREAT|0666);
+ if (msgid < 0) {
+ perror("Cannot create message queue");
+ exit(1);
+ }
+ /* Main body: loop over requests */
+ while (1) {
+ msgrcv(msgid, &msg_read, sizeof(int), 1, MSG_NOERROR);
+ n = random() % i; /* select random value */
+ strncpy(msg_write.mtext, fortune[n], MSGMAX);
+ size = min(strlen(fortune[n])+1, MSGMAX);
+ msg_write.mtype=msg_read.pid; /* use request pid as type */
+ msgsnd(msgid, &msg_write, size, 0);
+ }
+}
+/*
+ * Signal Handler to manage termination
+ */
+void HandSIGTERM(int signo) {
+ msgctl(msgid, IPC_RMID, NULL); /* remove message queue */
+ exit(0);
+}
+ \end{lstlisting}
+ \end{minipage}
+ \normalsize
+ \caption{Sezione principale del codice del server di \textit{fortunes}
+ basato sulle \textit{message queue}.}
+ \label{fig:ipc_mq_fortune_server}
+\end{figure}
+
+In \figref{fig:ipc_mq_fortune_server} si è riportato un estratto delle parti
+primcipali del codice del nuovo server (il codice completo è nel file
+\file{MQFortuneServer.c} nei sorgenti allegati). Il programma è basato su un
+uso accorto della caratteristica di poter associate un ``tipo'' ai messaggi
+per permettere una comunicazione indipendente fra il server ed i vari client,
+usando il \acr{pid} di questi ultimi come identificativo. Questo è possibile
+in quanto, al contrario di una fifo, la lettura di una coda di messaggi può
+non essere sequanziale, proprio grazie alla classificazione dei messaggi sulla
+base del loro tipo.
+
+Il programma, oltre alle solite variabili per il nome del file da cui leggere
+le \textit{fortunes} e per il vettore di stringhe che contiene le frasi,
+definisce due strutture appositamente per la comunicazione; con
+\var{msgbuf\_read} (\texttt{\small 8--11}) vengono passate le richieste mentre
+con \var{msgbuf\_write} (\texttt{\small 12--15}) vengono restituite le frasi.
+
+La gestione delle opzioni si è al solito omessa, essa si curerà di impostare
+in \var{n} il numero di frasi da leggere specificato a linea di comando ed in
+\var{fortunefilename} il file da cui leggerle; dopo aver installato
+(\texttt{\small 19--21}) dei manipolatori per gestire l'uscita dal server,
+viene prima controllato (\texttt{\small 22}) il numero di frasi richieste
+abbia senso (cioè sia maggiore di zero), le quali poi (\texttt{\small 23})
+vengono lette nel vettore in memoria con la stessa funzione
+\code{FortuneParse()} usata anche per il server basato sulle fifo.
+
+Una volta inizializzato il vettore di stringhe coi messaggi presi dal file
+delle \textit{fortune} si procede (\texttt{\small 25}) con la generazione di
+una chiave per identificare la coda di messaggi (si usa il nome del file dei
+sorgenti del server) con la quale poi si esegue (\texttt{\small 26}) la
+creazione della stessa (si noti come si sia chiamata \func{msgget} con un
+valore opportuno per l'argomento \param{flag}), avendo cura di abortire il
+programma (\texttt{\small 27--29}) in caso di errore.
+
+Finita la fase di inizializzazione il server esegue in permanenza il ciclo
+principale (\texttt{\small 32--41}). Questo inizia (\texttt{\small 33}) con il
+porsi in attesa di un messaggio di richiesta da parte di un client; si noti
+infatti come \func{msgrcv} richieda un messaggio con \var{mtype} uguale a 1:
+questo è il valore usato per le richieste dato che corriponde al \acr{pid} di
+\cmd{init}, che non può essere un client. L'uso del flag \macro{MSG\_NOERROR}
+è solo per sicurezza, dato che i messaggi di richiesta sono di dimensione
+fissa (e contengono solo il \acr{pid} del client).
+
+Se non sono presenti messaggi di richiesta \func{msgrcv} si bloccherà,
+ritornando soltanto in corrispondenza dell'arrivo sulla coda di un messaggio
+di richiesta da parte di un client, in tal caso il ciclo prosegue
+(\texttt{\small 34}) selezionando una frase a caso, copiandola (\texttt{\small
+ 35}) nella struttura \var{msgbuf\_write} usata per la risposta e
+calcolandone (\texttt{\small 36}) la dimensione.
+
+Per poter permettere a ciascun client di ricevere solo la risposta indirizzata
+a lui il tipo del messaggio in uscita viene inizializzato (\texttt{\small 37})
+al valore del \acr{pid} del client ricevuto nel messaggio di richiesta.
+L'ultimo passo del ciclo (\texttt{\small 38}) è inviare sulla coda il
+messaggio di risposta. Si tenga conto che se la coda è piena anche questa
+funzione potrà bloccarsi fintanto che non venga liberato dello spazio.
+
+Si noti che il programma può terminare solo grazie ad una interruzione da
+parte di un segnale; in tal caso verrà eseguito il manipolatore
+\code{HandSIGTERM}, che semplicemente si limita a cancellare la coda
+(\texttt{\small 44}) ed ad uscire (\texttt{\small 45}).
+
+\begin{figure}[!bht]
+ \footnotesize \centering
+ \begin{minipage}[c]{15cm}
+ \begin{lstlisting}{}
+int main(int argc, char *argv[])
+{
+ ...
+ key = ftok("./MQFortuneServer.c", 1);
+ msgid = msgget(key, 0);
+ if (msgid < 0) {
+ perror("Cannot find message queue");
+ exit(1);
+ }
+ /* Main body: do request and write result */
+ msg_read.mtype = 1; /* type for request is always 1 */
+ msg_read.pid = getpid(); /* use pid for communications */
+ size = sizeof(msg_read.pid);
+ msgsnd(msgid, &msg_read, size, 0); /* send request message */
+ msgrcv(msgid, &msg_write, MSGMAX, msg_read.pid, MSG_NOERROR);
+ printf("%s", msg_write.mtext);
+}
+ \end{lstlisting}
+ \end{minipage}
+ \normalsize
+ \caption{Sezione principale del codice del client di \textit{fortunes}
+ basato sulle \textit{message queue}.}
+ \label{fig:ipc_mq_fortune_client}
+\end{figure}
+
+In \figref{fig:ipc_mq_fortune_client} si è riportato un estratto il codice del
+programma client. Al solito il codice completo è con i sorgenti allegati, nel
+file \file{MQFortuneClient.c}. Come sempre si sono rimosse le parti relative
+alla gestione delle opzioni, ed in questo caso, anche la dichiarazione delle
+variabili, che, per la parte relative alle strutture usate per la
+comunicazione tramite le code, sono le stesse viste in
+\figref{fig:ipc_mq_fortune_server}.
+
+Il client in questo caso è molto semplice; la prima parte del programma
+(\texttt{\small 4--9}) si occupa di accedere alla coda di messaggi, ed è
+identica a quanto visto per il server, solo che in questo caso \func{msgget}
+non viene chiamata con il flag di creazione in quanto la coda deve essere
+preesistente. In caso di errore (ad esempio se il server non è stato avviato)
+il programma termina immediatamente.
+
+Una volta acquistito l'identificatore della coda il client compone il
+messaggio di richiesta (\texttt{\small 12--13}) in \var{msg\_read}, usando 1
+per il tipo ed inserendo il proprio \acr{pid} come dato da passare al server.
+Calcolata (\texttt{\small 14}) la dimensione, provvede (\texttt{\small 15}) ad
+immettere la richiesta sulla coda.
+
+A questo punto non resta che (\texttt{\small 16}) rileggere dalla coda la
+risposta del server richiedendo a \func{msgrcv} di selezionare i messaggi di
+tipo corrispondente al valore del \acr{pid} inviato nella richiesta. L'ultimo
+passo (\texttt{\small 17}) prima di uscire è quello di stampare a video il
+messaggio ricevuto.
+
+Benché funzionante questa archietettura risente dello stesso inconveniente
+visto anche nel caso del precedente server basato sulle fifo; se il client
+viene interrotto dopo l'invio del messaggio di richiesta e prima della lettura
+della risposta, quest'ultima resta nella coda (così come per le fifo si aveva
+il problema delle fifo che restavano nel filesystem). In questo caso però il
+problemi sono maggiori, sia perché è molto più facile esaurire la memoria
+dedicata ad una coda di messaggi che gli inode di un filesystem, sia perché,
+con il riutilizzo dei \acr{pid} da parte dei processi, un client eseguito in
+un momento successivo potrebbe ricevere un messaggio non indirizzato a
+lui.
+
+