Problema chiusura programma Server - Client

di il
0 risposte

Problema chiusura programma Server - Client

Vi spiego in poche parole, ho un problema nella chiusura da parte del codice del server.c in un ciclo if, precisamente (counter!=num_data). Negli altri if, si chiude immediatamente la connessione, qui no, molto probabilmente perchè si trova dentro ad un ciclo/loop, quello del while dove chiedi in input i dati. Precisamente quando inserisci i dati dove risulta il counter?num_data, succede che mi si chiude, ma prima mi chiede per un un'ultima volta i dati in input, ma la consegna del compito mi chiede di chiudere la connessione e inviare un messaggio al client. I codici sono questi. 

SERVER.C

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <math.h>

const char WELCOME_MESSAGE[] = "OK START Benvenuto, mandami i tuoi dati\n";
const char OK_DATA_MESSAGE[] = "OK DATA ";
const char OK_STATS_MESSAGE[] = "OK STATS ";
const char ERR_SYNTAX_MESSAGE[] = "ERR SYNTAX Il messaggio non è sintatticamente corretto.\n";
const char ERR_VARIANZA[] = "ERR STATS Non posso calcolare la varianza di 1 campione.\n";
const char ERR_ZEROVALORI[] = "ERR STATS Non posso calcolare media e varianza se non ho nessun valore.\n";
const char ERR_COERENTE[] = "ERR DATA Il valore dichiarato non è coerente con il contenuto del messaggio.\n";

double potenza(double base, int esponente) {
    double risultato = 1.0;

    if (esponente > 0) {
        for (int i = 0; i < esponente; i++) {
            risultato *= base;
        }
    } else if (esponente < 0) {
        for (int i = 0; i > esponente; i--) {
            risultato /= base;
        }
    }

    return risultato;
}

void calcola_media_varianza(const int *dati, int num_dati, double *media, double *varianza) {
    *media = 0.0;
    *varianza = 0.0;

    // Calcola la media
    for (int i = 0; i < num_dati; i++) {
        *media += dati[i];
    }
    *media /= num_dati;

    // Calcola la varianza
    for (int i = 0; i < num_dati; i++) {
        *varianza += potenza(dati[i] - *media, 2);
    }
    *varianza /= num_dati;
}


int main(int argc, char *argv[]) {
    int simpleSocket = 0;
    int simplePort = 0;
    int returnStatus = 0;
    //variabili per salvare dati caricati
    int* dati_ricevuti = NULL;
    int numerototale = 0;
    struct sockaddr_in simpleServer;

    if (2 != argc) {
        fprintf(stderr, "Usage: %s <port>\n", argv[0]);
        exit(1);
    }

    simpleSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

    if (simpleSocket == -1) {
        fprintf(stderr, "Could not create a socket!\n");
        exit(1);
    } else {
        fprintf(stderr, "Socket created!\n");
    }

    simplePort = atoi(argv[1]);

    memset(&simpleServer, '\0', sizeof(simpleServer));
    simpleServer.sin_family = AF_INET;
    simpleServer.sin_addr.s_addr = htonl(INADDR_ANY);
    simpleServer.sin_port = htons(simplePort);

    returnStatus = bind(simpleSocket, (struct sockaddr *)&simpleServer, sizeof(simpleServer));

    if (returnStatus == 0) {
        fprintf(stderr, "Bind completed!\n");
    } else {
        fprintf(stderr, "Could not bind to address!\n");
        close(simpleSocket);
        exit(1);
    }

    returnStatus = listen(simpleSocket, 5);

    if (returnStatus == -1) {
        fprintf(stderr, "Cannot listen on socket!\n");
        close(simpleSocket);
        exit(1);
    }

    while (1) {
        struct sockaddr_in clientName = {0};
        int simpleChildSocket = 0;
        int clientNameLength = sizeof(clientName);

        simpleChildSocket = accept(simpleSocket, (struct sockaddr *)&clientName, &clientNameLength);

        if (simpleChildSocket == -1) {
            fprintf(stderr, "Cannot accept connections!\n");
            close(simpleSocket);
            exit(1);
        }

        write(simpleChildSocket, WELCOME_MESSAGE, strlen(WELCOME_MESSAGE));

        while (1) {
            char buffer[512];
            int bytes_received = read(simpleChildSocket, buffer, sizeof(buffer) - 1);
            if (bytes_received <= 0) {
                perror("Error receiving data from client");
                close(simpleChildSocket);
                break;
            }

            buffer[bytes_received] = '\0';

            //variabile che indica il numero di dati da caricare
            //primo numero che si scrive
            int num_data;

            if (sscanf(buffer, "%d", &num_data) != 1) {
                // Invia messaggio di errore sintattico
                write(simpleChildSocket, ERR_SYNTAX_MESSAGE, strlen(ERR_SYNTAX_MESSAGE));
                continue;
            }

            int counter = 0;

            if (num_data > 0) {
                // Alloca un array per memorizzare i dati
                //int data[num_data];

                dati_ricevuti = (int*)realloc(dati_ricevuti, (numerototale + num_data) * sizeof(int));
                if (dati_ricevuti == NULL) {
                  fprintf(stderr, "Errore nell'allocazione di memoria.\n");
                  close(simpleChildSocket);
                  break;
                }

                //ciclo for per tenere traccia dei valori inseriti
                //aumento counter
                //cosi da controllare con num_data se i valori sono uguali
                //altrimenti errore e chiudo connessione
                for (int j = 0; buffer[j] != '\0' && buffer[j] != '\n'; j++) {
                  // Incrementa il contatore solo se il carattere corrente è uno spazio
                  if (buffer[j] == ' ') {
                    counter++;

                    // Ignora gli spazi bianchi consecutivi
                    //per evitare di contare uno spazio in più come valore in più
                    while (buffer[j + 1] == ' ') {
                      j++;
                    }

                    // Verifica se il prossimo carattere è '\0' e decrementa il contatore se necessario
                    if (buffer[j + 1] == '\0') {
                      counter--;
                    }
                  }
                }

                //debug
                //printf("Ricevuti %d dati: ", num_data);

                char *data_str = strtok(buffer, " "); // Prima chiamata a strtok
                for (int i = 0; i < num_data; i++)
                {
                    data_str = strtok(NULL, " "); // Chiamate successive a strtok
                    if (data_str == NULL)
                    {
                        fprintf(stderr, "Errore nella lettura dei dati.\n");
                        close(simpleChildSocket);
                        break;
                    }
                    dati_ricevuti[numerototale + i] = atoi(data_str);
                    // debug
                    // printf("%d ", dati_ricevuti[numerototale + i]);
                }

                printf("Ricevuti %d dati: \n", num_data);
                fflush(stdout);

                printf("Ricevuti %d contatore: \n", counter);
                fflush(stdout);

                if (counter != num_data) {
                  // Invia il messaggio di errore al client
                  write(simpleChildSocket, ERR_COERENTE, strlen(ERR_COERENTE));

                  // Libera la memoria e chiudi la connessione
                  numerototale = 0;
                  free(dati_ricevuti);

                  // Chiudi la connessione
                  close(simpleChildSocket);
                  close(simpleSocket);

                  // Esci immediatamente dal programma
                  exit(1);
                }
                // Invia OK DATA con il numero totale di dati ricevuti
                char ok_data_message[256];
                sprintf(ok_data_message, "%s%d\n", OK_DATA_MESSAGE, num_data);
                write(simpleChildSocket, ok_data_message, strlen(ok_data_message));

                numerototale+=num_data;

                double mean, variance;
                calcola_media_varianza(dati_ricevuti, num_data, &mean, &variance);

                // Invia OK STATS con il risultato
                //char ok_stats_message[256];
                //sprintf(ok_stats_message, "%s%d %.1f %.1f\n", OK_STATS_MESSAGE, num_data, mean, variance);
                //write(simpleChildSocket, ok_stats_message, strlen(ok_stats_message));
            } else {
              //debug
              // Stampa l'array completo
              //printf("Array completo: ");
              //for (int i = 0; i < numerototale; i++) {
                  //printf("%d ", dati_ricevuti[i]);
              //}
              //printf("\n");

              // Caso in cui il client manda 0 dati
              if(numerototale==0){
                  //se ho 0 valori non posso calcolare media e varianza
                  // Invia messaggio di errore sintattico
                  write(simpleChildSocket, ERR_ZEROVALORI, strlen(ERR_ZEROVALORI));
              }
              else if(numerototale==1){
                  //Se ho un solo valore non posso calcolare varianza
                  // Invia messaggio di errore sintattico
                  write(simpleChildSocket, ERR_VARIANZA, strlen(ERR_VARIANZA));
              }
              else{
                  // Invia OK STATS con il risultato
                  double mean, variance;
                  calcola_media_varianza(dati_ricevuti, numerototale, &mean, &variance);

                  char ok_stats_message[256];
                  sprintf(ok_stats_message, "%s%d %.1f %.1f\n", OK_STATS_MESSAGE, numerototale, mean, variance);
                  write(simpleChildSocket, ok_stats_message, strlen(ok_stats_message));

                  //resettare tutto dopo calcolato media e varianza
                  //cosi ripeti i calcoli senza prendere i valori precedenti
                  //svuoto array e resetto a 0 il numero totale dei valori Array
                  numerototale = 0;
                  free(dati_ricevuti);

                  // Chiudi la connessione
                  close(simpleChildSocket);
                  break;
                }
            }
        }
    }
    //free(dati_ricevuti);

    close(simpleSocket);
    return 0;
}

CLIENT.C

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>

void send_message(int socket, const char *message) {
    send(socket, message, strlen(message), 0);
}

void receive_message(int socket) {
    char buffer[512];
    int bytes_received = read(socket, buffer, sizeof(buffer) - 1);

    if (bytes_received <= 0) {
        perror("Error receiving data from server");
        close(socket);
        exit(1);
    }

    buffer[bytes_received] = '\0'; // Termina la stringa ricevuta

    // Stampa il messaggio ricevuto
    printf("S: %s\n", buffer);
}

int main(int argc, char *argv[]) {
    int simpleSocket = 0;
    int simplePort = 0;
    int returnStatus = 0;
    char buffer[256] = "";
    struct sockaddr_in simpleServer;

    if (3 != argc) {
        fprintf(stderr, "Usage: %s <server> <port>\n", argv[0]);
        exit(1);
    }

    simpleSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

    if (simpleSocket == -1) {
        fprintf(stderr, "Could not create a socket!\n");
        exit(1);
    } else {
        fprintf(stderr, "Socket created!\n");
    }

    simplePort = atoi(argv[2]);

    memset(&simpleServer, '\0', sizeof(simpleServer));
    simpleServer.sin_family = AF_INET;
    simpleServer.sin_addr.s_addr = inet_addr(argv[1]);
    simpleServer.sin_port = htons(simplePort);

    returnStatus = connect(simpleSocket, (struct sockaddr *)&simpleServer, sizeof(simpleServer));

    if (returnStatus == 0) {
        fprintf(stderr, "Connect successful!\n");
    } else {
        fprintf(stderr, "Could not connect to address!\n");
        close(simpleSocket);
        exit(1);
    }


    // Ricevi il messaggio di benvenuto dal server
    receive_message(simpleSocket);

    // Invia i dati al server
       while (1) {
           printf("C: ");
           fgets(buffer, sizeof(buffer), stdin);

           // Rimuovi il carattere di nuova riga dalla stringa
           size_t len = strlen(buffer);
           if (len > 0 && buffer[len - 1] == '\n') {
               buffer[len - 1] = '\0';
           }

           send_message(simpleSocket, buffer);

           // Ricevi e stampa la risposta del server
           receive_message(simpleSocket);

           if (strcmp(buffer, "0") == 0) {
               break;
           }
       }

       close(simpleSocket);

       return 0;
   }
Devi accedere o registrarti per scrivere nel forum
0 risposte