La comunicazione tra client e server avviene tramite socket di tipo AF_UNIX.
In breve: ho un processo che simula il client che richiede operazioni al server che, se legali, le esegue.
Il server è strutturato con:
- un main che esegue la parte di inizializzazione e che nel ciclo while principale esegue la poll e mette in coda i file descriptor che vogliono comunicare;
- un thread listener che esegue in un while la funzione accept
- dei thread worker che prelevano le richieste dalla coda (la stessa del main) e eseguono le operazioni richieste.
Durante l'esecuzione ho un problema e non riesco a capire da che cosa è dovuto.
La fase di inizializzazione avviene quasi correttamente. Dico quasi perchè il path di dove avviene la creazione del socket mi da qualche problema.
Lato server eseguo il parsing di un file di configurazione da cui estraggo alcune informazioni come il path. Esso ha lunghezza 20 ma la funzione sizeof mi restituisce come dimensione 8.
Lato client passo il path direttamente al main ma anche in esso la funzione sizeof mi restituisce 8 e non 20.
Al momento ho deciso, quindi, di troncare il path a 8 caratteri.
Tuttavia il problema più grande ce l'ho nel main e in particolare nella funzione poll.
il client funziona correttamente e crea la connessione con questa funzione:
Codice: Seleziona tutto
int openConnection(char* path, unsigned int ntimes, unsigned int secs){
int fd_clt=-1, i;
//alloco e riempio la struttura per l'indirizzo
struct sockaddr_un sa;
strncpy(sa.sun_path, path, sizeof(path));
sa.sun_family=AF_UNIX;
if((fd_clt=socket(AF_UNIX, SOCK_STREAM, 0))==-1){
perror("socket");
return -1;
}
//provo a connettermi
for(i=0;i<ntimes;i++){
if((connect(fd_clt, (struct sockaddr*)&sa, sizeof(sa)))==-1){
perror("connect");
sleep(secs);
}
else{
return fd_clt;
}
}
return -1;
}Per provare a farlo funzionare ho decrementato nel server questo fd così che concida con quello del client (Non so se sia giusto farlo ma mi da errore se gli fd sono diversi).
Il client viene messo nel set della poll dal thread listener e poi dal main dovrei essere notificato quando il client scrive qualcosa.
Il problema è proprio questo, che non vengo notificato! Sono sicuro che il client scriva qualcosa sul socket ma nonostante ciò la poll mi restituisce sempre 0. Allego le parti di codice principali del main e del listener. Ringrazio chiunque mi voglia aiutare
LISTENER:
Codice: Seleziona tutto
static void *listener(void *arg){
int new_fd=0, count_err=0, trovato=0, i=0, err=0, temp=0;
printf("Sono il listener\n");
//while in cui eseguo l'accept e controllo gli eventuali errori
while (kill_all==0){
printf("LISTENER: Inizio ciclo while\n");
if((new_fd=accept(fd_skt, NULL, 0))==-1){
printf("LISTENER: ERRORE accept\n");
temp=errno;
switch(temp){
case EWOULDBLOCK: { //socket impostato come non bloccante e nessuna connessione è in attesa di essere accettata
count_err=0;
} break;
default:{
fprintf(stderr,"Errore nella funzione accept; Funzione listener\n");
perror("accept");
if(count_err>3){ //non termino subito se è presente un errore ma solo se ce ne sono 3 consecutivi
exit(EXIT_FAILURE);
}
else{
count_err++;
//aggiorno le statistiche:errori++
if((update_stats(0,0,0,0,0,0,1,0,0))!=0)
fprintf(stderr, "Errore nell'aggiornamento delle statistiche\n");
}
}break;
}
}
else{
printf("LISTENER: accept terminata, fd=%d\n",new_fd);
count_err=0;
//inserisco il nuovo fd nella poll
trovato=i=0;
if((err=pthread_mutex_lock(&mux_poll))!=0){
errno=err;
fprintf(stderr,"Errore nel prendere la lock; Funzione listener; Struttura poll\n");
perror("lock");
//aggiorno le statistiche:errori++
if((update_stats(0,0,0,0,0,0,1,0,0))!=0)
fprintf(stderr, "Errore nell'aggiornamento delle statistiche\n");
exit(EXIT_FAILURE);
}
while((i<size_poll) && (trovato==0)){
if(poll_set[i].fd==-1){
poll_set[i].fd=(new_fd-1);
trovato=1;
if((modify_pollusers_number(1))!=0){ //incremento il valore degli utenti del set della poll
fprintf(stderr,"Errore nel decrementare il numero di utenti della poll; Funzione main\n");
//aggiorno le statistiche:errori++
if((update_stats(0,0,0,0,0,0,1,0,0))!=0)
fprintf(stderr, "Errore nell'aggiornamento delle statistiche\n");
exit(EXIT_FAILURE);
}
if((modify_users_number(1))!=0){ //incremento il valore degli utenti totali
fprintf(stderr,"Errore nel decrementare il numero di utenti totali; Funzione main\n");
//aggiorno le statistiche:errori++
if((update_stats(0,0,0,0,0,0,1,0,0))!=0)
fprintf(stderr, "Errore nell'aggiornamento delle statistiche\n");
exit(EXIT_FAILURE);
}
}
else
i++;
}
if((err=pthread_mutex_unlock(&mux_poll))!=0){
errno=err;
fprintf(stderr,"Errore nel rilasciare la lock; Funzione listener; Struttura poll\n");
perror("unlock");
//aggiorno le statistiche:errori++
if((update_stats(0,0,0,0,0,0,1,0,0))!=0)
fprintf(stderr, "Errore nell'aggiornamento delle statistiche\n");
exit(EXIT_FAILURE);
}
printf("LISTENER: inserito il client alla posizione i=%d\n", i);
}
printf("LISTENER: finito ciclo while\n");
}
exit(EXIT_SUCCESS);
}MAIN:
Codice: Seleziona tutto
//while principale in cui controllo il risultato della poll
int ret=0, count=0, count_err=0, local_fd=0;
while(kill_all==0){
if((err=pthread_mutex_lock(&mux_poll))!=0){
errno=err;
fprintf(stderr, "Errore nel prendere la lock; Funzione main; Struttura poll\n");
perror("lock");
//aggiorno le statistiche:errori++
if((update_stats(0,0,0,0,0,0,1,0,0))!=0)
fprintf(stderr, "Errore nell'aggiornamento delle statistiche\n");
return -1;
}
if((err=pthread_mutex_lock(&mux_pollusers))!=0){
errno=err;
fprintf(stderr,"Errore nel prendere la lock; Funzione listener; Variabile users\n");
perror("lock");
//aggiorno le statistiche:errori++
if((update_stats(0,0,0,0,0,0,1,0,0))!=0)
fprintf(stderr, "Errore nell'aggiornamento delle statistiche\n");
return -1;
}
ret=poll(poll_set, pollusers, 0);
//printf("Main: numero utenti poll=%d\n", pollusers);//CONTROLLARE SE NON FUNZIONA. INSERIRE FORSE NUEMRO DI FD DA CONTROLLARE INVECE DEL MAX FD
if((err=pthread_mutex_unlock(&mux_pollusers))!=0){
errno=err;
fprintf(stderr,"Errore nel prendere la lock; Funzione listener; Variabile users\n");
perror("lock");
//aggiorno le statistiche:errori++
if((update_stats(0,0,0,0,0,0,1,0,0))!=0)
fprintf(stderr, "Errore nell'aggiornamento delle statistiche\n");
return -1;
}
if((err=pthread_mutex_unlock(&mux_poll))!=0){
errno=err;
fprintf(stderr,"Errore nel rilasciare la lock; Funzione main; Struttura poll\n");
perror("unlock");
//aggiorno le statistiche:errori++
if((update_stats(0,0,0,0,0,0,1,0,0))!=0)
fprintf(stderr, "Errore nell'aggiornamento delle statistiche\n");
return -1;
}
switch(ret){
case (-1):{ //la poll ha restituito un errore
switch(errno){
case EINTR:{ //la poll è stata interrotta da un segnale
} break;
default:{
count_err++;
//aggiorno le statistiche:errori++
if((update_stats(0,0,0,0,0,0,1,0,0))!=0)
fprintf(stderr, "Errore nell'aggiornamento delle statistiche\n");
if(count_err>3){ //ci sono stati 3 errori consecutivi quindi termino il server
perror("poll");
failure++;
}
else
fprintf(stderr,"La poll ha restituito un errore; Funzione server\n");
}break;
}
}break;
case(0):{ //la poll è stata interrotta dal timeout e nessun evento è stato registrato
} break;
default:{ //tutto è andato a buon fine e la poll ha restituito il numero di fd con attività
printf("Main ho trovato il client\n");
if (ret<-1){
fprintf(stderr,"Errore nella funzione poll; Funzione main\n");
//aggiorno le statistiche:errori++
if((update_stats(0,0,0,0,0,0,1,0,0))!=0)
fprintf(stderr, "Errore nell'aggiornamento delle statistiche\n");
count_err++;
break;
}
count=0;
i=0;
while(i<size_poll || count==ret){ //cerco gli fd con attività
if((err=pthread_mutex_lock(&mux_poll))!=0){
errno=err;
fprintf(stderr, "Errore nel prendere la lock; Funzione main; Struttura poll\n");
perror("lock");
//aggiorno le statistiche:errori++
if((update_stats(0,0,0,0,0,0,1,0,0))!=0)
fprintf(stderr, "Errore nell'aggiornamento delle statistiche\n");
return -1;
}
if(poll_set[i].fd!=-1){
if(poll_set[i].revents & POLLIN){ //un client ha qualche operazione da svolgere
count++;
poll_set[i].revents=0;
//acquisisco la lock sulla lista delle operazioni
if((err=pthread_mutex_lock(&mux_fd_operation))!=0){
errno=err;
fprintf(stderr, "Errore nel prendere la lock; Funzione main; Struttura fd_operation\n");
perror("lock");
//aggiorno le statistiche:errori++
if((update_stats(0,0,0,0,0,0,1,0,0))!=0)
fprintf(stderr, "Errore nell'aggiornamento delle statistiche\n");
return -1;
}
//inserisco nella lista l'fd del client che vuole svolgere un'operazione
if(fd_operation==NULL){
fd_operation=(fd_list*)malloc(sizeof(fd_list));
fd_operation->fd=poll_set[i].fd;
fd_operation->next=NULL;
}
else{
fd_list *corr=fd_operation;
while(corr->next!=NULL)
corr=corr->next;
corr->next=(fd_list*)malloc(sizeof(fd_list));
corr=corr->next;
corr->fd=poll_set[i].fd;
corr->next=NULL;
}
if((err=pthread_cond_signal(&cond_operation))!=0){ //faccio una signal per svegliare un worker
errno=err;
fprintf(stderr,"Errore nell'effetuare la signal; Funzione main; Struttura fd_operation\n");
perror("signal");
//aggiorno le statistiche:errori++
if((update_stats(0,0,0,0,0,0,1,0,0))!=0)
fprintf(stderr, "Errore nell'aggiornamento delle statistiche\n");
return -1;
}
if((err=pthread_mutex_unlock(&mux_fd_operation))!=0){
errno=err;
fprintf(stderr,"Errore nel rilasciare la lock; Funzione main; Struttura fd_operation\n");
perror("unlock");
//aggiorno le statistiche:errori++
if((update_stats(0,0,0,0,0,0,1,0,0))!=0)
fprintf(stderr, "Errore nell'aggiornamento delle statistiche\n");
return -1;
}
poll_set[i].fd=-1; //lo levo dal set della poll e lo inserisco, dal worker, alla fine dell'operazione
if((modify_pollusers_number(-1))!=0){ //decremento il numero di utenti dal set della poll
fprintf(stderr,"Errore nel decrementare il numero di utenti della poll; Funzione main\n");
//aggiorno le statistiche:errori++
if((update_stats(0,0,0,0,0,0,1,0,0))!=0)
fprintf(stderr, "Errore nell'aggiornamento delle statistiche\n");
failure++;
}
}
...EDIT: dovrei aver risolto quel problema ma appena provo a leggere con la read quello che mi scrive il client mi viene restituito questo errore: Read: Connection reset by peer
Cosa significa questo errore? Come potrei sistemarlo?