0

I'm studying sockets and client server communication with select. My problem is that at line 261 i get the Bad File Descriptor error and I have no idea why. The message on line 233 arrives to the client, in the one after (line 252) the client instead of receiving the size in bytes receives 0, and in the write after (line 261) I get the error. I'm really confused.

This is the SERVER

#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#define DIM_BUFF         100
#define max 10
#define mass(a, b)        ((a) > (b) ? (a) : (b))

/********************************************************/
void gestore(int signo) {
    int stato;
    printf("esecuzione gestore di SIGCHLD\n");
    wait(&stato);
}
/********************************************************/

//STRUTTURA DATI

typedef struct{
    char Targa[max];
    int  Patente;
    char Tipo[max];
    char Folder[max];
}Prenotazione;

//REQUEST DATAGRAM

typedef struct{
    char Targa[max];
    int newPatente[max];
}Request;

int main(int argc, char **argv) {
    //inizializziamo struttura
    Prenotazione pren[3];
    //dati mock
   strcpy(pren[0].Targa,"ciao1");
    pren[0].Patente=1234;
    strcpy(pren[0].Tipo,"tipo1");
    strcpy(pren[0].Folder,"prova1");
     
    strcpy(pren[1].Targa,"ciao2");
    pren[1].Patente=1234;
    strcpy(pren[1].Tipo,"tipo2");
    strcpy(pren[1].Folder,"prova2");

    strcpy(pren[2].Targa,"ciao3");
    pren[2].Patente=1234;
    strcpy(pren[2].Tipo,"tipo3");
    strcpy(pren[2].Folder,"prova3");
    printf("struttura dati inizializzata!!\n");

    int       listenfd, connfd, udpfd, nready, maxfdp1;
    const int on   = 1;
    FILE* fd_file;
    char      zero = '\0' ,Targa[max],fileName[20],path[128];
    int buff[DIM_BUFF];
    fd_set    rset;
    int       len, nread, nwrite, num, port,count=0;
    long size;
    struct sockaddr_in cliaddr, servaddr;
    Request           *req = (Request *)malloc(sizeof(Request));
    DIR           *dir1;
    struct dirent *dd1;

    /* CONTROLLO ARGOMENTI ---------------------------------- */
    if (argc != 2) {
        printf("Error: %s port\n", argv[0]);
        exit(1);
    }
    nread = 0;
    while (argv[1][nread] != '\0') {
        if ((argv[1][nread] < '0') || (argv[1][nread] > '9')) {
            printf("porta non intero\n");
            exit(2);
        }
        nread++;
    }
    port = atoi(argv[1]);
    if (port < 1024 || port > 65535) {
        printf("Porta scorretta...");
        exit(2);
    }

        /* INIZIALIZZAZIONE INDIRIZZO SERVER ----------------------------------------- */
    memset((char *)&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family      = AF_INET;
    servaddr.sin_addr.s_addr = INADDR_ANY;
    servaddr.sin_port        = htons(port);

    printf("Server avviato\n");

    /* CREAZIONE SOCKET TCP ------------------------------------------------------ */
    listenfd = socket(AF_INET, SOCK_STREAM, 0);
    if (listenfd < 0) {
        perror("apertura socket TCP ");
        exit(1);
    }
    printf("Creata la socket TCP d'ascolto, fd=%d\n", listenfd);

    if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
        perror("set opzioni socket TCP");
        exit(2);
    }
    printf("Set opzioni socket TCP ok\n");

    if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
        perror("bind socket TCP");
        exit(3);
    }
    printf("Bind socket TCP ok\n");

    if (listen(listenfd, 5) < 0) {
        perror("listen");
        exit(4);
    }
    printf("Listen ok\n");

    /* CREAZIONE SOCKET UDP ------------------------------------------------ */
    udpfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (udpfd < 0) {
        perror("apertura socket UDP");
        exit(5);
    }
    printf("Creata la socket UDP, fd=%d\n", udpfd);

    if (setsockopt(udpfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
        perror("set opzioni socket UDP");
        exit(6);
    }
    printf("Set opzioni socket UDP ok\n");

    if (bind(udpfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
        perror("bind socket UDP");
        exit(7);
    }
    printf("Bind socket UDP ok\n");

    /* AGGANCIO GESTORE PER EVITARE FIGLI ZOMBIE -------------------------------- */
    signal(SIGCHLD, gestore);

     /* PULIZIA E SETTAGGIO MASCHERA DEI FILE DESCRIPTOR ------------------------- */
    FD_ZERO(&rset);
    maxfdp1 = mass(listenfd, udpfd) + 1;

     /* CICLO DI RICEZIONE EVENTI DALLA SELECT ----------------------------------- */
    for (;;) {
        FD_SET(listenfd, &rset);
        FD_SET(udpfd, &rset);

         if ((nready = select(maxfdp1, &rset, NULL, NULL, NULL)) < 0) {
            if (errno == EINTR)
                continue;
            else {
                perror("select");
                exit(8);
            }
        }

        //GESTIONE RICHIESTE CAMBIO NUMERO PATENTE--------------------

        if (FD_ISSET(udpfd, &rset)) {
            int result=-1;
            printf("Server: ricevuta richiesta di cambio numero patente\n");
            len = sizeof(struct sockaddr_in);
            if (recvfrom(udpfd, req, sizeof(Request), 0, (struct sockaddr *)&cliaddr, &len) <
                0) {
                perror("recvfrom");
                continue;
            }

        printf("targa: %s \n", req->Targa);
        printf("nuovo numero patente: %s \n", req->newPatente);

        for(int i=0;i<3 && result==-1;i++){
            if(strcmp(req->Targa,pren[i].Targa)==0){
                pren[i].Patente=*req->newPatente;
                result=0;
            }
        }

        printf("cambio numero patente effettuato!, invio risposta... \n");

        if (sendto(udpfd, &result, sizeof(result), 0, (struct sockaddr *)&cliaddr, len) < 0) {
                perror("sendto");
                continue;
            }

        }//IF UDP

        //GESTIONE RICHIESTE SCARICAMENTO IMMAGINI
        if (FD_ISSET(listenfd, &rset)) {
            printf("Ricevuta richiesta di get di un file\n");
            len = sizeof(struct sockaddr_in);
            if ((connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &len)) < 0) {
                if (errno == EINTR)
                    continue;
                else {
                    perror("accept");
                    exit(9);
                }
            }
            if (fork() == 0) { /* processo figlio che serve la richiesta di operazione */
                close(listenfd);
                printf("Dentro il figlio, pid=%i\n", getpid());
                char Fold[max];
                int trovato=-1;

                while ((nread = read(connfd, &Targa, sizeof(Targa))) > 0) {
                    printf("Server (figlio): targa richiesta: %s\n", Targa);
                    for(int i=0;i<3;i++){
                        if(strcmp(Targa,pren[i].Targa)==0){
                            strcpy(Fold,pren[i].Folder);
                            trovato=i;
                        }
                    }

                    if(trovato>=0){

                    dir1 = opendir(Fold);
                    while ((dd1 = readdir(dir1)) != NULL) {
                            if (strcmp(dd1->d_name, ".") != 0 && strcmp(dd1->d_name, "..") != 0) {
                                strcpy(fileName, dd1->d_name);
                                if (write(connfd, fileName,(strlen(fileName) + 1)) < 0) {
                                   perror("Errore nell'invio del nome file\n");
                                   continue;
                                }
                                path[0] = '\0'; //path reset
                sprintf(path, "%s/%s", pren[trovato].Folder, dd1->d_name);
                                fd_file = fopen(path, "rb");
                                if (fd_file < 0) {
                                printf("ERRORE Apertura FILE\n");
                                
                   
                                
                                } 
                                fseek(fd_file, 0, SEEK_END);
                                size=ftell(fd_file);
                                fseek(fd_file, 0, SEEK_SET);

                                printf("le dimensioni sono: %ld" ,size);
                                //invio la dimensione
                                if (write(connfd, &size,sizeof(long))< 0) {
                                   perror("Errore nell'invio della dimensione file\n");
                                   exit(0);
                                }

                                 /* lettura dal file (a blocchi) e scrittura sulla socket */
                                 printf("Leggo e invio il file richiesto\n");
                                while (count<size) {
                                 nread = fread(buff, sizeof(int), sizeof(buff),fd_file);
                                 if (nwrite = write(connfd, buff, sizeof(buff)) < 0) {

                                perror("write");
                                break;
                                }
                                bzero(buff, sizeof(buff));
                                count=count+nread;
                             }
                              printf("Terminato invio file\n");
                              
                              fclose(fd_file);
                            }
                    }//while DD1
                    strcpy(fileName,"fine");
                    if (write(connfd, fileName,(strlen(fileName) + 1)) < 0) {
                        perror("Errore nell'invio del nome file\n");
                         continue;
                    }
                    printf("Terminato invio di tutti i file\n");
                    closedir(dir1);

                    }//if trovato
                    else{
                        strcpy(fileName,"errore");
                    if (write(connfd, fileName,(strlen(fileName) + 1)) < 0) {
                        perror("Errore nell'invio del nome file\n");
                         continue;
                    }
                    }


                }//while richieste

                printf("Figlio TCP terminato, libero risorse e chiudo. \n");
                close(connfd);
                exit(0);
                
            }//FORK

            sleep(1);
            close(connfd); //padre chiude la socket(non di ascolto)
            
        }//IF TCP



    }//for SELECT


}//main

this is the CLIENT

#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>

#define DIM_BUFF         100
#define LENGTH_FILE_NAME 20



int main(int argc, char *argv[]) {
    int                sd, nread, port,count=0;
    char                nome_file[LENGTH_FILE_NAME],Targa[10];
    struct hostent    *host;
    struct sockaddr_in servaddr;
    int c;
    long size;

    /* CONTROLLO ARGOMENTI ---------------------------------- */
    if (argc != 3) {
        printf("Error:%s serverAddress serverPort\n", argv[0]);
        exit(1);
    }
    printf("Client avviato\n");

    /* PREPARAZIONE INDIRIZZO SERVER ----------------------------- */
    memset((char *)&servaddr, 0, sizeof(struct sockaddr_in));
    servaddr.sin_family = AF_INET;
    host                = gethostbyname(argv[1]);
    if (host == NULL) {
        printf("%s not found in /etc/hosts\n", argv[1]);
        exit(2);
    }

    nread = 0;
    while (argv[2][nread] != '\0') {
        if ((argv[2][nread] < '0') || (argv[2][nread] > '9')) {
            printf("Secondo argomento non intero\n");
            exit(2);
        }
        nread++;
    }
    port = atoi(argv[2]);
    if (port < 1024 || port > 65535) {
        printf("Porta scorretta...");
        exit(2);
    }

    servaddr.sin_addr.s_addr = ((struct in_addr *)(host->h_addr))->s_addr;
    servaddr.sin_port        = htons(port);

    /* CREAZIONE E CONNESSIONE SOCKET (BIND IMPLICITA) ----------------- */
    sd = socket(AF_INET, SOCK_STREAM, 0);
    if (sd < 0) {
        perror("apertura socket ");
        exit(3);
    }
    printf("Creata la socket sd=%d\n", sd);

    if (connect(sd, (struct sockaddr *)&servaddr, sizeof(struct sockaddr)) < 0) {
        perror("Errore in connect");
        exit(4);
    }
    printf("Connect ok\n");

    //inizio ciclo richieste

      printf("numero della targa o EOF: \n");

    while (gets(Targa)) {

        if (write(sd, Targa, (strlen(Targa) + 1)) < 0) {
            perror("write");
            continue;
        }
        printf("Richiesta della targa %s inviata... \n", Targa);

        //ricezione nome file ogni volta

        if (read(sd, &nome_file, sizeof(nome_file)) < 0) {
            perror("read");
            break;
        }
        while(strcmp(nome_file,"fine")!=0 ){
            FILE* f;
            printf("il nome del file: %s \n" ,nome_file);
            if (read(sd, &size, sizeof(long)) < 0) {
            perror("read");
            break;
            }
            if(size==0){
                printf("size 0");
                exit(1);
            }
            printf("la size e': %ld" ,size);
            f=fopen(nome_file,"wb");
            while (count<size){
               nread = read(sd, &c, 1);
               fwrite(&c,sizeof(int),1,f);
               count=count+nread;
            }
            fclose(f);
            printf("immagine ricevuta\n");
            if (read(sd, &nome_file, sizeof(nome_file)) < 0) {
            perror("read");
            break;
            }
            



        }
        if(strcmp(nome_file,"fine")==0){
            printf("tutte le immaigini ricevute\n");
            printf("numero della targa o EOF: \n");

        }
        else{
            printf("ERRORE PROTOCOLLO\n");
            shutdown(sd, 0);
             shutdown(sd, 1);
            close(sd);
            exit(0);
        }
    }//whilw

printf("\nClient: termino...\n");
    shutdown(sd, 0);
    shutdown(sd, 1);
    close(sd);
    exit(0);
}//main

I've literally tried everything but it doesn't seem to work. Thanks for your time and sorry form my bad english.

  • Please trim your code to make it easier to find your problem. Follow these guidelines to create a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example). – Community Jan 19 '23 at 18:51
  • You are probably reading a file size of 0 because the client doesn't know how many bytes to read for the filename and its null terminator and tries to read `sizeof(nome_file)` bytes regardless. It should probably read the filename one byte at a time until it reads the null terminator, then it will know that the next `sizeof(long)` bytes will contain the file size. – Ian Abbott Jan 19 '23 at 18:56
  • If any of the filenames are longer than 19 characters, `strcpy(fileName, dd1->d_name);` will have undefined behavior in the server. – Ian Abbott Jan 19 '23 at 19:01
  • See also: [Why is the `gets` function so dangerous that it should not be used?](https://stackoverflow.com/q/1694036/2505965) – Oka Jan 19 '23 at 19:08
  • 1
    Which line is line 261? – user253751 Jan 19 '23 at 19:53
  • 1
    "Bad file descriptor" means the socket number that you told it to read from wasn't actually a socket number. It means you closed the socket, or you used the wrong number. – user253751 Jan 19 '23 at 19:53

0 Answers0