Ciao a tutti, vi scrivo perchè ho un problema per quanto riguarda la comunicazione tra client e server. Devo creare una chat per scambiare messaggi tra diversi client, questi client devono anche potersi registrare, effettuare login e logout. Per quanto riguarda il login e la registrazione sono riuscito a implementare il tutto in maniera funzionante, il problema sorge quando un utente deve fare il logout. Mi spiego meglio, se si connette un solo client il problema non sussiste e il logout avviene correttamente, se invece ne collego 2 il server invia il comando di logout solo all'ultimo client connesso lasciando in attesa indefinita il primo client. Vi posto il codice del thread che effettua queste operazioni e il relativo codice del client
thread del server:
/////////////////////////////////////////////////////////////
//gestione comunicazione col client
void *worker(void *threadarg) {
char *read_sender, *read_receiver, *read_msglen, *msg;
char read_msg[80];
char buffer[1000], risposta[1000];
char *tok, *key, ret, *token;
int msglen, i = 0;
const char *space= " ", s[2] =":";
int *csd= (int*) threadarg;
msg_t messaggio;
hdata_t *trovato;
FILE *fp;
memset(buffer, 0 ,1000); //inizializzo a zero i campi del buffer
memset(read_msg, 0, 80);
//close(msd); // closing master socket
// leggiamo tutti i dati dalla socket e salviamo in un buffer
read(*csd, buffer, 1000);
// elaboriamo il buffer per recuperare i campi della struttura
// il primo carattere e' il tipo
messaggio.type = buffer[0];
printf("MESSAGGIO.TYPE = %c\n", messaggio.type);
if(messaggio.type == MSG_LOGIN) {
strtok(buffer, " ");
msglen = atoi(strtok(NULL, " "));
msg = strtok(NULL, " ");
printf("QUELLO CHE HO RICEVUTO: %c %d %s\n", messaggio.type, msglen, msg);
trovato = CERCAHASH(msg, hash);
if(trovato != NULL) {
ret = MSG_OK;
write(*csd, &ret, sizeof(char));
trovato->sockid = 1; //utente connesso
} else {
ret = MSG_ERROR;
write(*csd, &ret, sizeof(char));
}
}
if(messaggio.type == MSG_REGLOG) {
if((fp = fopen("user-file.txt", "a+")) == NULL) {
fprintf(stderr, "File non aperto\n");
exit(1);
} else
printf("aperto con successo\n");
strtok(buffer, " ");
msglen = atoi(strtok(NULL, " "));
// il messaggio potrebbe contenere spazi, quindi ogni token va a comporre il messaggio
while((tok=strtok(NULL, " ")) != NULL) {
if(strlen(read_msg) != 0) // prima di aggiungere il token letto mettiamo uno spazio, ma non all'inzio
strcat(read_msg,space);
strcat(read_msg,tok);
}
printf("read_msg %s\n", read_msg);
fprintf(fp, "%s\n", (char*)read_msg); //salvo l'utente appena iscritto sul file
fflush(fp);
fclose(fp);
funzionehash("user-file"); //carico la tabella degli utenti aggiornata
tok = strtok(read_msg, s); //salvo solo l'username per controllare che la registrazione abbia avuto successo
trovato = CERCAHASH(tok, hash);
if(trovato != NULL) {
ret = MSG_OK;
write(*csd, &ret, sizeof(char));
trovato->sockid = 1; //utente connesso
} else {
ret = MSG_ERROR;
write(*csd, &ret, sizeof(char));
}
}
while(go) {
memset(risposta, 0, 1000);
read(*csd, buffer, 1000);
messaggio.type = buffer[0];
if(messaggio.type == MSG_LIST) {
} else if(messaggio.type == MSG_BRDCAST) {
} else if(messaggio.type == MSG_SINGLE) {
} else if(messaggio.type == MSG_LOGOUT) {
strtok(buffer, " ");
key = strtok(NULL, " ");
trovato = CERCAHASH(key, hash);
if(trovato != NULL){
ret = MSG_OK;
trovato->sockid = 0; //utente disconnesso
} else {
ret = MSG_ERROR;
}
sprintf(risposta, "%c %c", messaggio.type, ret);
write(*csd, risposta, sizeof(risposta));
pthread_exit(NULL);
}
}
}
codice del client relativo al logout
while(go) {
messaggio.msg = malloc(SL * sizeof(char));
memset(buffer, 0, 1000); //riazzero il campo buffer
memset(risposta, 0, 1000); //riazzero il campo buffer
printf("Digita un comando da inviare al server:\n");
scanf("%s", cmd);
while(getchar() != '\n');
if(strcmp(cmd, "ls") == 0) {
messaggio.type = MSG_LIST;
strcpy(messaggio.sender, user);
sprintf(buffer, "%c %s", messaggio.type, messaggio.sender);
} else if(strcmp(cmd, "dest") == 0) {
printf("digita un destinatario(per inviare il messaggio in broadcast scrivi *)\n");
scanf("%s", messaggio.receiver);
while(getchar() != '\n');
strcpy(messaggio.sender, user);
if(strcmp(messaggio.receiver, "*")==0){
messaggio.type = MSG_BRDCAST;
//messaggio.receiver = NULL;
} else {
messaggio.type = MSG_SINGLE;
}
printf("Digita il messaggio che vuoi inviare:\n");
fgets(messaggio.msg, 256, stdin);
messaggio.msglen = strlen(messaggio.msg);
sprintf(msg_len, "%d", messaggio.msglen);
sprintf(buffer, "%c %s %s %s %s", messaggio.type, messaggio.sender, messaggio.receiver, msg_len, messaggio.msg);
} else if(strcmp(cmd, "logout") == 0) {
messaggio.type = MSG_LOGOUT;
strcpy(messaggio.sender, user);
sprintf(buffer, "%c %s", messaggio.type, messaggio.sender);
} else {
fprintf(stderr, "Errore, comando %s non riconosciuto\n", cmd);
}
printf("BUFFER: %s\n", buffer);
write(sd, buffer, sizeof(buffer));
read(sd, risposta, sizeof(risposta)); //leggo la risposta
printf("RISPOSTA %s\n", risposta);
messaggio.type = risposta[0];
if(messaggio.type == MSG_LOGOUT) {
strtok(risposta, " ");
tok = strtok(NULL, " ");
strcpy(risp, tok);
if(risp[0] == MSG_OK) {
printf("Il server ha tornato %c, disconnessione in corso..\n", risp[0]);
//close(sd);
exit(1);
} else {
fprintf(stderr, "Il server ha tornato %c, Disconnessione non possibile\n", risp[0]);
}
} else if(messaggio.type == MSG_SINGLE) {
}
}
spero possiate aiutarmi.