Al solito, l'esercizio di comprensione del codice e' autocontenuto. Eseguite lo script seguente col vostro numero di matricola come argomento per avere la soluzione:
#!/bin/bash a=0 foo() { for i in $* ; do echo ${i##7} ; a=${#i}+$a ; done ; } bar() { typeset -a b; i=$1 j=0 while ((${#i}>1)) ; do b[$j]=$(($i%100)); i=$(($i/100)); j=1+$j; echo $(($j)) $i done ; echo ${#b[@]} foo ${b[*]} ; } bar $1 echo $a
Il testo chiede di definire un protocollo applicativo per registrazione e invio di messaggi, e di implementare il server che gestisce il sistema di comunicazione.
Il protocollo contiene, naturalmente, due tipi di messaggi: il messaggio di registrazione e quello di invio di testo. Possiamo definire il messaggio di registrazione come “JOIN <#canale>\n”, mentre il messaggio di testo puo' essere preso come default (tutto cio' che non corrisponde ad un altro comando e' inteso come testo da inviare ai client).
Il server deve mantenere una lista di client (identificati dai loro descrittori di file), e associare a ciascun client il canale richiesto o nessun canale prima dell'arrivo del messaggio di registrazione; assumiamo un valore “non associato”, ad esempio:
#define NOCHAN -1
Ai fini della soluzione, la lista puo' essere sostituita da un array, per evitare la complessita' (peraltro non enorme) della creazione dinamica della struttura dati.
Notate che, siccome il client puo' scegliere di cambiare il canale in uso, e' piu' semplice realizzare un server multi-thread o sequenziale che non un server multiprocesso.
Nel caso del server sequenziale (consigliato per semplicita'), si impiega la funzione select
per attendere una scrittura su uno o piu' dei file descriptor associati ai client, come visto nell'esempio presentato a lezione.
La differenza rispetto a quel caso sta nel fatto che, in risposta alla lettura di un messaggio “JOIN <#canale>\n” il server deve aggiornare la lista dei client con l'informazione opportuna, mentre per qualunque altra stringa s
letta dal descrittore fd
, deve svolgere le seguenti operazioni:
for(sender=list_head; sender->fd!=fd && sender!=NULL; curr=sender->next); if (sender==NULL) error(); for(curr=list_head; curr!=NULL; curr=curr->next) if (curr->chan==sender->chan) write(curr->fd,s, strlen(s));
Notate che sono possibili molte altre soluzioni, questa e' solo quella che mi sembra piu' semplice.