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);
}
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);
}