+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 dei tipi di 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.
+
+
+Oltre alle solite variabili per il nome del file delle fifo e per il vettore
+di stringhe che contiene le frasi, il programma utilizza due strutture 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 restituire
+in \var{n} il numero di file da leggere ed in \var{fortunefilename} il file da
+cui leggerle; dopo aver installato (\texttt{\small 19--21}) dei manipolatori
+per gestire l'uscita prima viene controllato (\texttt{\small 22}) che si siano
+richiesti un numero positivo di messaggi, che poi (\texttt{\small 23}) vengono
+letti 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 fortunes si procede (\texttt{\small 25}) con la generazione di una
+chiave (si usa il nome del file dei sorgenti del server) con la quale poi si
+esegue (\texttt{\small 26}) la creazione della nostra coda di messaggi (si
+noti come si sia chiamata \func{msgget} con un valore opportuno per il 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,
+che è 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.
+
+Se non sono presenti messaggi di richiesta \func{msgrcv} si bloccherà;
+all'arrivo sulla coda di un messaggio di richiesta da parte di un client la
+funzione ritorna, ed 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 ricevuto nel messaggio di richiesta. L'ultimo passo del ciclo
+(\texttt{\small 38}) è inviare sulla coda il messaggio di risposta.
+
+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.
+
+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.
+
+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.
+