#include <sys/types.h> // includo le librerie di interesse #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #include <stdio.h> #include <signal.h> #include <sys/stat.h> #include "mio.h" //prototipi di funzioni void gestoreSig1(int); // funzione per gestire la terminazione di un figlio void gestoreSig2 (int); // funzione per chiudere i figli void gestoreUscita (int); // gestisco l'uscita Control +C void salvataggio (); // salvo in un unico file i numeri trovati int figli_necessari=0; // numero che dipende dall'intervallo e dal quanto numero int num_figli =0; // è uguale al numero di client che si è connesso int main (int argc, char *argv[]) { int ds_sock, ds_sock_acc; struct sockaddr_in server; // struttura del server struct sockaddr client; // struttura del client int lunghezza; // misura in byte della struttura client effettivamente usati char ip_server [20]="128.0.0.0"; //IP del server char buffer[BUF_DIM]; //per trasmettere messaggi long numero; // per trasmettere i numeri dell'intervallo int porta_TCP; // porta di comunicazione long primo_numero, ultimo_numero,inf,sup; // primo e ultimo numero dell'intervallo da analizzare long quanto; // dimensione dei pacchetti int pid; // pid del figlio int controlla = 0; // misura dell'intervallo controllato FILE *fp; char nome_file [12]; // nome dei file creati dai figli if (argc<5) // controllo il numero di argomenti inseriti { printf ("Inserire %s <porta_TCP> <primo_intero> <secondo_intero> <dim_pacchetti>\n",argv[0]); exit(-1); } porta_TCP = atoi (argv[1]); // inizializzo le variabili con gli argomenti inseriti primo_numero= atol(argv[2]); ultimo_numero = atol (argv[3]); quanto = atol (argv[4]); if (primo_numero<2) // controllo alcune caratteristiche dei numeri introdotti { printf ("<primo_numero> deve essere maggiore di 1\n"); exit(-1); } if (primo_numero >= ultimo_numero) // controllo l'ordine dell'intervallo { printf ("<ultimo_numero> deve essere maggiore di <primo_numero>\n"); exit(-1); } figli_necessari = (ultimo_numero-primo_numero)/quanto; // rapporto tra interi è intero if (((ultimo_numero-primo_numero)%quanto) !=0) figli_necessari++; // ho un figlio che lavorerà con meno di un quanto printf("\n"); printf("Premere Control + C per uscire\n"); if ((ds_sock = socket(AF_UNIX,SOCK_STREAM,0))==-1) // creo il soket { printf ("Errore di socket\n"); printf ("Impossibile avviare il Server\n"); exit(-1); } server.sin_family = AF_UNIX; // imposto la struttura dati del socket server.sin_port = porta_TCP; server.sin_addr.s_addr = inet_addr(ip_server); //converto l'indirizzo da stringa in unsigned long printf ("ds server %d\n",ds_sock); // visualizzo impostazioni socket printf ("Server IP : %s \n",inet_ntoa (server.sin_addr.s_addr)); printf ("Porta di connessione : %d\n",porta_TCP); printf ("Numero figli necessari : %d\n",figli_necessari); if((bind (ds_sock, &server, sizeof(server)))==-1) // effettuo bind del socket creato { printf ("Bind fallito \n"); printf ("Impossibile avviare il Server\n"); exit(-1); } if ((listen (ds_sock,CODA_DIM)) ==-1) //imposto la coda dei client printf("Impossibile accodare client\n"); while(2) //ciclo infinito { printf("*******************************************\n"); printf("Sono in attesa di connessioni \n"); while ((ds_sock_acc = accept (ds_sock, &client, &lunghezza))==-1); // attendo connessione client printf("Un client si è connesso\n"); printf ("ds client %d\n",ds_sock_acc); if (controlla >= (ultimo_numero-primo_numero) ) // se l'intervallo è controllato blocco i client write(ds_sock_acc,"fine",BUF_DIM); // avviso dello stato con il messaggio fine else // asssegno ad un altro client il pacchetto e risorse necessarie { num_figli++; // aumento il numero dei figli attivati = client accettati controlla = quanto*num_figli; // imposto l'intervallo controllato inf = primo_numero + quanto*(num_figli-1); sup = inf+quanto-1; if (sup> ultimo_numero) sup= ultimo_numero; // non controllo numeri oltre l'intervallo; signal (SIGUSR1,gestoreSig1); // armo il segnale pid = fork(); // se l'intervallo è completo non creo altri figli if (pid == -1) { printf ("Impossibile creare un nuovo figlio \n"); exit (-1); // non attendo il liberarsi delle risorse di sistema } if (pid!=0) { signal (SIGUSR2,SIG_IGN); // ignoro il segnale 2 di utente (chiude i figli) signal (SIGINT,gestoreUscita); // armo il segnale di uscita per i salvataggi necessari } else //sono il figlio { close (ds_sock); signal (SIGUSR2,gestoreSig2); //armo il segnale read(ds_sock_acc,buffer,BUF_DIM); printf("messaggio ricevuto %s \n",buffer); write(ds_sock_acc,"OK",BUF_DIM); // invia il messaggio OK al client write(ds_sock_acc,&inf,sizeof(inf)); // invia l'intervallo al client write(ds_sock_acc,&sup,sizeof(sup)); sprintf (nome_file,"%d",num_figli); // creo nome file con indice del figlio (univoco) if ((fp=fopen(nome_file, "w")) == NULL) { printf ("Impossibile aprire il file \n"); exit(-1); } do // scrivo nel file i numeri inviati dal client { read(ds_sock_acc,&numero,sizeof(numero)); if (numero!= 0) fprintf (fp,"%d ",numero); // con 0 il client segnala la fine dell'analisi pacchetto } while (numero!=0); // chiudo il file aperto dal figlio if ((fclose (fp))== -1 ) printf ("Impossibile chiudere file %s \n", nome_file); if ((close(ds_sock_acc)) == -1) printf ("Impossibile chiudere soket\n"); while (kill(getppid(),SIGUSR1)==-1); // invio al padre il segnale usr1 // segnalando fine del figlio exit (0); // termine del figlio } } } // ritorno all'inizio del ciclo infinito } // gestisco le azioni da compiere prima di uscire void gestoreUscita (int sig) { kill (0,SIGUSR2); // invio il segnale a tutti i figli, il padre lo ignora salvataggio(); exit(1); } //gestisco i figli che terminano void gestoreSig1 (int sig) { static figli_terminati = 0; // inizializzo la variabile solo la prima volta figli_terminati++; printf ("Figlio è terminato %d°°°°°°°°°\n",figli_terminati); if (figli_terminati == figli_necessari) salvataggio(); } // gestisco la chiusura del figlio sotto il volere del padre void gestoreSig2 (int sig) { printf("Figlio PID : %d chiuso\n",getpid()); exit(-1); // chiudo il figlio } // effettuo il salvataggio dei file nell'unico file FINAL.DAT void salvataggio () { int i,j=0; // i contatore file letti j contatore numeri scritti per andare poi a capo int numero; // per la lettura dei numeri nei file char nome_file [12]; FILE *fp,*fp_finale; printf("___________________________________________\n"); printf("I CLIENT HANNO TERMINATO L'ELABORAZIONE\n"); printf("\n"); printf("exit file : FINAL.DAT\n"); printf("___________________________________________\n"); if ((fp_finale=fopen("FINAL.DAT", "w")) == NULL) { printf ("Impossibile salvare i risultati\n"); exit(-1); } for (i=1; i <=num_figli; i++) { sprintf (nome_file,"%d",i); // creo il nome del file dall'indice if ((fp=fopen(nome_file, "r")) == NULL) { printf ("Impossibile aprire file per salvataggio finale %s\n",nome_file); continue; } while (fscanf(fp,"%d",&numero)!=EOF) { if ((++j%10)==0) fprintf(fp_finale,"\n"); // salto una riga ogni 10 numeri scritti fprintf(fp_finale,"%d ",numero); // trasferisco il contenuto dei file in FINAL.DAT } close(fp); //cancella il file letto if ((remove(nome_file)) == -1 ) printf ("Impossibile rimuovere il file %s \n",nome_file); } close(fp_finale); exit(0); }