0

I'm beginning with c in we were asked to create a small TCP/IP application in C language. In the beginning i was doing just fine, i have tested the server and the client and they were communicating but when i started to develop the main subject of the application which is: a client connect to the server and ask for a book by it's reference. the server it self reads a file which contains lines of some books written as follow(reference;name of the author;title;gender), as you can see in the code i wanted to read the file and store every line in a 2 dimension table.

And then the server compare the reference sent by the client and compare it with what i have in the tables and if it exists, he will send the info of that book to the client.(Sorry, too much phrases but I'm trying to make it clear as possible as i can). therefore when i compile the server and try to execute it, i got a segmentation fault... :(. here is the code. If you could help that would be perfect !.

 #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #include <signal.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/wait.h>
    #include <errno.h>
    
    
    #define MAX_LIGNE 256
    
    /*typedef struct{
        int numRef;
        char nomAuteur[50];
        char titre[50];
        char genre[20];
    } biblio ;*/
    
    void handler(int sig){
        wait(NULL);
    }
    
    int main (int argc, char **argv){
        struct sigaction ac;
    
        ac.sa_handler = &handler;
        ac.sa_flags = SA_RESTART;
        char ligne[61];
        char *elem=(char *)malloc(sizeof(char)*100);
        int i=0;
        //biblio tab[30];
        char *tab[50][4]={0};
        //Stockage des données du fichier dans un tableau
        //ouverture du fichier en lecture seule
        //char *fichier=";
        FILE * fd;
        fd=fopen("./fichier-exemple.txt","r");
        if(fd==NULL){
            printf("Erreur lors de l'ouverture du fichier...\n");
        }
    
        //on stock les données du fichier dans la table de structure
    
        while(fgets(ligne,sizeof(ligne),fd)!=NULL){
    
            
        elem=strtok(ligne,";");
        tab[i][0]=(char *)malloc(strlen(elem)*sizeof(char));
        strcpy(tab[i][0],elem);
        
        elem=strtok(NULL,";");                  
        tab[i][1]=(char *)malloc(strlen(elem)*sizeof(char));
        strcpy(tab[i][1],elem); 
        
        elem=strtok(NULL,";");
        tab[i][2]=(char *)malloc(strlen(elem)*sizeof(char));
        strcpy(tab[i][2],elem); 
        
        elem=strtok(NULL,"\n");
        tab[i][3]=(char *)malloc(strlen(elem)*sizeof(char));
        strcpy(tab[i][3],elem); 
        i++;
        }
                            
        free(elem);
        fclose(fd);
        int longeur=i;
        //vérification du nombre d'arguments
        if(argc!=2){
            fprintf(stderr,"respectez la synthaxe: serveur <port> !\n");
            exit(0);
        } else {
    
        
        int port=atoi(argv[1]);
        //les structures s et c pour server et client respectivement
        struct sockaddr_in s,c;
    
        //création de socket
    
        int p=socket(AF_INET,SOCK_STREAM,0);
    
        if(p<0){
            printf("Erreur lors de la création du socket....\n");
            exit(0);
        }else{
            printf("Socket créé avec succès....\n");
            }
        //remplissage de la structure s
        s.sin_family=AF_INET;
        s.sin_addr.s_addr=htonl(INADDR_ANY);
        s.sin_port=htons(port);
    
        socklen_t Slen= (socklen_t)sizeof(c);
    
        //création de bind
    
        int b= bind(p,(const struct sockaddr *)&s, Slen);
        if(b<0){
            printf("Erreur lors du bind...\n");
            exit(0);
        }else{
            printf("Bind créé avec succès...\n");
        }
    
        //l'écoute
    
        int l= listen(p,20);
    
        if(l==-1){
            printf("Erreur d'écoute ...\n");
            exit(0);
        }else{
            printf("En écoute...\n");
            
        }
        //boucle infini pour accepter les demandes des clients
        while(1){
            int acpt=accept(p,(struct sockaddr *) &c, &Slen);
            if(acpt==-1){
                printf("Erreur d'acceptation...\n");
            }else{
                printf("Acceptation...\n");
            }
            int f=fork();
            if(f==0){
                char * res=(char *)calloc(MAX_LIGNE,sizeof(char));
                char  * buffer=(char *)calloc(MAX_LIGNE,sizeof(char));
                while(1){
                    
                    //réception du trajet depuis le client
                    //recv(acpt,buffer,MAX_LIGNE,0);
                    recv(acpt, &buffer, strlen(buffer),0);
                    int buf=atoi(buffer);
                    
                    //char ligne[50];
    
                    int j=0;
                    for(j=0;j<longeur;j++){
                    //printf("%s",tab[j].genre);
                        if(atoi(tab[j][0])==buf){
                            strcpy(res,tab[j][1]);
                            strcat(res, ", ");
                            strcat(res,tab[j][2]);
                            strcat(res, ", ");
                            strcat(res,tab[j][3]);
                            strcat(res,"\n");
                        }
                    }
    
                        
    
    
                    send(acpt,&res,strlen(res),0);
                }
                free(buffer);
                free(res);
            }else{
                sigaction(SIGCHLD,&ac,NULL);
            }
        }
        }
    }
SimoDev
  • 1
  • 2
  • You're not doing anything with your SIGCHLD handler. Setting `ac.sa_handler = SIG_IGN;` to ignore SIGCHLD will do a better job making sure child processes get reaped. See https://stackoverflow.com/questions/40601337/what-is-the-use-of-ignoring-sigchld-signal-with-sigaction2 – Andrew Henle Dec 02 '20 at 18:25

1 Answers1

1
            char * res=(char *)calloc(MAX_LIGNE,sizeof(char));
            ...
            send(acpt,&res,strlen(res),0);

You passed &res to send. But res is a pointer to the data you want to send. You don't want to actually send res to the other side -- it's a pointer whose value is only meaningful to this process.

Change &res to res. You need to pass send a pointer to the data you want to send, not a pointer to the address at which the data you want to send is stored.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
  • i did the both changes suggested by you guys but still have the segmentation fault :( – SimoDev Dec 02 '20 at 18:58
  • You're going to have to fix your other bugs too. For example, your calls to `malloc` don't allocate enough space to hold the terminating zero byte. – David Schwartz Dec 02 '20 at 19:40
  • oh okey ! so i should do (char *)malloc(strlen(elem)*sizeof(char)+1); is that right ? – SimoDev Dec 02 '20 at 19:53
  • @mohamedaitlaadik That will work. `sizeof(char)` is defined as 1 since `sizeof` returns the result in characters. So you can remove that part. – David Schwartz Dec 02 '20 at 19:54