// ESEMPIO DI SOLUZIONE DI UNO STUDENTE // // //file #include //socket #include //printf #include #include //exit #include #include //file #include //file #include #include //segnali affidabili,kill #include //fork,segnali,pipe,file,sleep,alarm,pause #include //nanosleep #include //fork,getpid(),waitpid(),socket,file #include //wait,waitpid() #include void error(char *msg) { perror(msg); exit(0); } int main(){ srand(time(NULL)); //P1 int P1,P2; int piped[2]; int c,j; if(pipe(piped)<0) { perror("pipe"); exit(-1); } P1=getpid(); if ((P2=fork()) < 0) { perror("fork error"); exit(1); } else if (P2 == 0) //P2 { sleep(5); // attende 5 sec //Generazione di 5 figli int pid; for(j=0;j<5;j++){ if ((pid=fork()) < 0) { perror("fork error"); exit(1); } else if (pid == 0) //figlio { int sockfd, portno, n; struct sockaddr_in serv_addr; struct hostent *server; char send_buffer[256]; char rec_buffer[256]=""; portno = 10000+j; printf("Figlio di P2 con pid=%d :provo a comunicare con P1 tramite la porta %d\n",getpid(), portno); sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) error("ERRORE in apertura"); server = gethostbyname("localhost"); if (server == NULL) { fprintf(stderr,"ERRORE, l’host non esiste\n"); exit(0); } serv_addr.sin_family = AF_INET; memcpy((char *)&serv_addr.sin_addr,(char *)server->h_addr,server->h_length); serv_addr.sin_port = htons(portno); if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0) sleep(-1);//se non c'e' una connesione sospende il processo int PID; PID=getpid(); n = write(sockfd,&PID,sizeof(int)); if (n < 0) error("ERRORE in scrittura sulla socket"); printf("Figlio di P2 con pid=%d: sono riuscito a connettermi con P1 tramite la porta %d e termino\n",getpid(), portno); close(sockfd); exit(0); } //P2 write(piped[1], &pid, sizeof (int)); } //P2 printf("P2:ho generato 5 figli. Adesso aspetto che terminino\n"); while ((waitpid(-1, NULL, 0)) > 0); printf("P2:Sono terminati tutti i miei figli; ora termino anche io\n"); exit(0); } else //P1 { int sockfd, newsockfd, portno, clilen, PID; struct sockaddr_in serv_addr, cli_addr; sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) error("ERRORE DI APERTURA DELLA SOCKET"); portno = 10000+rand() %5; // portno e' un numero casuale fra 10000 e 10004 serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_port = htons(portno); if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) error("ERRORE DI BINDING"); listen(sockfd,5); clilen = sizeof(cli_addr); printf("P1:sto in ascolto sulla porta %d\n",portno); newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen); if (newsockfd < 0) error("ERRORE DI ACCEPT"); int n; n = read(newsockfd,&PID,sizeof(int)); if (n < 0) perror("ERRORE in lettura dalla socket"); printf("P1:Ho recevuto un client di PID %d\n",PID); int PidX; for(j=0;j<5;j++){ n = read(piped[0],&PidX, sizeof (int)); if (n < 0) perror("ERRORE in lettura dalla socket"); if (PidX!=PID) { printf("P1 :Mando un seganle SIGKILL al figlio con Pid %d per terminarlo\n",PidX); kill(PidX,SIGKILL); } } close(sockfd); close(newsockfd); printf("P1:Aspetto che P2 termini\n"); while ((wait(NULL)) > 0); printf("P1: P2 e' terminato; termino anche io\n"); } }