PDA

View Full Version : [C] Client/Server - Il mio server si rifiuta di accettare piu client, ne vuole uno


ginter87
26-02-2010, 20:10
Uff!
Il mio elaborato riguarda una videointerrogazione in rete dove il server è il professore mentre i clients sono gli studenti.

Il mio problema è che io vorrei che il prof invii inizialmente la prima domanda a tutti gli studenti, poi uno di loro risponde, entra in sez critica, gli altri aspettano lui risponde e quando ha terminato si passa alla domanda successiva.

Ciò non avviene O_O

Il mio server prende e accetta il primo ... gli manda le domande aspettando le risposte, fa tutti i controlli di correttezza, assegnamento punteggio poi chiude e finisce mentre invece dovrebbe partecipare anche l'altro client.

Ho provato ad aprire 3 terminali, dove uno è il server e gli altri due sono i client e non so se magari questo "errore" è dovuto all'esecuzione in locale oppure no ...

vi metto il codice ... ditemi, sigh io ho esame l'8 marzo ... sigh
grazie anticipatamente

CODICE SERVER

#include <stdio.h> // per I/O

#include <stdlib.h> // per exit, malloc, atoi...

#include <unistd.h> // per exec, getpid...

#include <pthread.h> // thread

#include <semaphore.h> //semafori posix

#include <sys/types.h> // standard posix
#include <netinet/in.h> //

#include <sys/socket.h> // socket

#include <signal.h> // segnali

#include <string.h>
#include <pthread.h>
#include <sys/types.h>
#include <semaphore.h>
#include <sys/types.h>

#include <semaphore.h>

#include <fcntl.h>

#define totpost 3 //numero studenti

#define MAX 3 //numero domande
#define LEN 1024 //caratteri per riga: 1023+0 del messaggio
#define PORT 16000 //porta dove il server accetta le connessioni

#define semaforo "sem_mutex"

#define MACS 2


char domande[MAX][LEN]; //tabella caricata con domande e risposte
char risposte[MAX][2]; //tabella caricata con le risposte corrette

void *caricamento(void *arg); //funzione svolta dal thread1
char risp[2];
sem_t *mutex;
int sd, i, j, k;
int punteggi[MAX][MACS], punteggio;
int tab[totpost][2];
struct sockaddr_in server_addr; // struttura dati di configurazione

struct sockaddr_in client_addr;

socklen_t client_len;



int main(int argc, char *argv[])

{

system("clear"); //system chiama il comando UNIX "clear"
printf("Server avviato con pid = %d\n", getpid());

int i;
//THREAD
int res, pid;
pthread_t thread1; //primo thread per il caricamento
void *thread_result;
res=pthread_create(&thread1, NULL, caricamento,NULL);
if (res!=0)
{ perror("\n****ERRORE CREAZIONE THREAD***\n");
exit(1);
}
res=pthread_join(thread1, &thread_result); //come la wait
printf("thread1 terminato con stato: %d\n", (int*)thread_result);
//FINE THREAD


//inizializzo il vettore punteggi
for(j=0;j<2;j++)
for(i=0;i<totpost;i++)
{
punteggi[i][j]=0;
punteggi[i][j]=0;
}
//fine


//VISUALIZZAZIONE DOMANDE PER CONFERMA CARICAMENTO
printf("\n\n******ELENCO DOMANDE******\n");
for(k=0;k<MAX;k++)
printf("Domanda numero %d:\t%s\nRisposta Corretta:\t%s\n\n",k+1,domande[k],risposte[k]);

//SOCKET
int client_sd[totpost];
// preparazione dei dati relativi al bind

server_addr.sin_family = AF_INET; //dominio

server_addr.sin_port = htons(PORT); //host to network

server_addr.sin_addr.s_addr = INADDR_ANY; //associa al server l'indirizzo della macchina

client_len = sizeof(struct sockaddr_in);



//SOCKET
int sd=socket(AF_INET, SOCK_STREAM, 0);//restituisce l'identificativo del socket
if(sd<0)
{
perror("creazione socket errata!!\n");
exit(-1);
}
//BIND
printf("Effettuo la bind del socket con la porta ds\n", PORT);

if (bind(sd, (const struct sockaddr *) &server_addr, client_len) < 0)

{

perror("Durante il bind\n");

exit(1);

}

//LISTEN

printf("Mi metto in attesa di connessioni sulla porta %d\n", PORT);

if (listen(sd, 2) < 0)

{

perror("Durante il listen");

exit(1);

}



printf("Entro nel ciclo for in cui accetto connessioni\n");


// itero il tutto cn un ciclo for ke crea un sd dedicato per ogni client accettato

for(i=0;i<totpost;i++)
{
//ACCEPT: accetta le commessioni che gli arrivano

client_sd[i] = accept(sd, (struct sockaddr *) &client_addr, &client_len);
if (client_sd[i] < 0)
{
perror("Durante l'accept\n");
exit(1);
}
//FORK: creazione figli
pid = fork();


if (pid == 0) //FIGLIO
{
printf("sono il servente: %d\n",getpid()); //figlio ke s collega con il client
printf("Connessione con client accettata sul socket %d\n", client_sd[i]);

break;
}
if(pid < 0) //ERRORE
{
printf("\n\n ERRORE FORK\n\n");
exit(1);
}
if(pid >0) //PADRE
{
sleep(2); //ASPETTA LA TERMINAZIONE DEI FIGLI ... MANCU PER METTERE NA WAIT
}

//CARICAMENTO TABELLE CON IDENTIFICATIVI ... pero' ci son pobbbbbemi
tab[i][0]=pid;
tab[i][1]=client_sd[i];


}



// crea/preleva un semaforo con valore iniziale a 1 (per noi un mutex)



mutex = sem_open(semaforo, O_CREAT, 0777, 1);

if (mutex == 0)

{

perror("sem_open");

exit(1);

}

else
{
for(k=0;k<MAX;k++) //conta le domande da inviare
{
printf(" \nInvio la %d domanda ... ", k+1);
for(i=0;i<totpost;i++)
{
if(send(client_sd[i],domande[k],strlen(domande[k]),0)>0)
{
printf(" \n*********** DOMANDA %d inviata ************ ", k+1);
printf("\nAttendo una risposta dagli studenti per circa 10 secondi\n");
sleep(10);
//ricevo la prima risposta quindi semaforo rosso per tutti gli altri

printf("\n");

printf("Attendo l'acquisizione del mutex\n");

if (sem_wait(mutex) < 0)

{

perror("Su sem_wait");

exit(1);

}

printf("Mutex acquisito correttamente\n");

printf("Effettuo tutte le operazioni\n");
res=recv(client_sd[i], risp, 2, 0);
if(res>0)
{
printf("\nRisposta ricevuta: \t %s\n",risp);
sleep(3);
printf("\n Effettuo il controllo di correttezza sulla risposta\n\n");
if(strcmp(risposte[k],risp)==0)
{
printf("\nLa risposta corretta è stata data dallo studente con ID %d\n",client_sd[i]);
punteggi[i][j]=client_sd[i];
punteggi[i][j+1]++;
}

}
sleep(1);
printf("Rilascio il mutex e dormo 1 secondo\n");

if (sem_post(mutex) < 0)

{

perror("Su sem_post");

exit(1);

}
}
}

}
}

for(i=0;i<totpost;i++)
printf("\nEcco i vari punteggi:\n\nID Studente: %d\t Punteggio: %d\n",client_sd[i],punteggi[i][j+1]);


close(sd);


printf("\n");
printf("\n\t\t ********************* ");
printf("\n\t\t * * ");
printf("\n\t\t * TERMINATO!!!!! * ");
printf("\n\t\t * * ");
printf("\n\t\t ********************* ");
printf("\n\n");
system("killall -q server");


} //FINE MAIN


/*THREAD CONTROLLO MAX E MIN PUNTEGGI
void *punteggi(void *args)
{
int i, j, temp;

for (i = (array_size - 1); i >= 0; i--)
{
for (j = 1; j <= i; j++)
{
if (numbers[j-1] > numbers[j])
{
temp = numbers[j-1];
numbers[j-1] = numbers[j];
numbers[j] = temp;
}
}
} da modificare ma è l'algoritmo bubble sort per ordinare in modo crescente o decrescente il vettore punteggio per decretare il "vincitore"
}*/








//THREAD CARICAMENTO DOMANDE

void *caricamento(void *args)
{
char s[1024];
char r[2];

int k;
int risp;
printf("\n\n******** CARICAMENTO DOMANDE START ******** ");
for(k=0; k<MAX; k++)
{
printf("\nInserisci la %d domanda e le 4 risposte\t \n", k+1);
gets(s);
if(strlen(s)==0)
{
printf("\nERRORE: STRINGA VUOTA!! REINSERIRE DATI NELLA DOMANDA");
k--;
}
else if(strlen(s)>LEN)
{
printf("\nERRORE: STRINGA GRANDE!! REINSERIRE DATI NELLA DOMANDA");
k--;
}
else
strcpy(domande[k], s);

printf("\nInserisci la %d risposta corretta\n", k+1);
gets(r);
if(strlen(r)==0)
{
printf("\nERRORE: STRINGA VUOTA NELLA RISPOSTA !! REINSERIRE DATI.");
k--;
}
else if(strlen(r)>1)
{
printf("\nERRORE: troppi caratteri, inserire una sola lettera nella risposta");
k--;
}
else
strcpy(risposte[k], r);



}

sleep(3);
pthread_exit(EXIT_SUCCESS);
}

//FINE THREAD CARICAMENTO DOMANDE




CODICE CLIENT

#include <sys/types.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <netdb.h>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <sys/types.h>




#define LEN 1024

#define PORT 16000
#define MAX 3




int sd, res, ress, i, j;
char risp[2], punt[2];




struct sockaddr_in server_addr;

struct hostent *hostinfo;

socklen_t len;



int main(int argc, char *argv[])

{

if (argc < 2)

{

printf("Utilizzo: ./%s <indirizzo>\nHai dimenticato di inserire l'indirizzo!!! \n", argv[0]);

exit(1);

}
system("clear");


//SOCKET

printf("Creo il socket\n");

sd = socket(PF_INET, SOCK_STREAM, 0);

if (sd < 0)

{

perror("Durante la creazione del socket\n");

exit(1);

}



// prepara i dati per la connessione con il server

server_addr.sin_family = AF_INET;

server_addr.sin_port = htons(PORT);

server_addr.sin_addr.s_addr = INADDR_ANY;



hostinfo = gethostbyname(argv[1]);



if (hostinfo == NULL)

{

printf("Non è stato possibile risolvere il nome del server\n");

exit(1);

}

else

server_addr.sin_addr = *((struct in_addr *) hostinfo->h_addr);



//CONNECT
printf("Apro la connessione\n");

if (connect(sd, (struct sockaddr *) &server_addr, sizeof(struct sockaddr_in)) < 0)

{

perror("Durante la connect");

exit(1);

}

//semaforo verde
printf(" ***************Ricevo la prima domanda e la visualizzo a schermo****************");
char buffer[MAX][LEN];
for(i=0;i<=MAX;i++)
{
res=recv(sd, buffer[i], LEN+1,0);
if(res>0)
{
printf("\nLa domanda a cui devi rispondere è: %s \n Inserisci il carattere corrispondente alla tua risposta\n", buffer[i]);
gets(risp);
sleep(3);
res=send(sd, risp, strlen(risp), 0);
if (res>0)
printf("\n La Risposta Inviata Correttamente è: \t %s\n",risp);
}
}

exit(0);
}