Forum Programmation.c socket serveur / client

Posté par  .
Étiquettes : aucune
0
24
mai
2006
Salut a tous.

je tente de realiser un systeme client / serveur, et mon systeme est presque fini, cependant j'ai segfault sur ma fermeture de socket client qui me laisse perplexe.

alors j'expose mon probleme :

j'ai un serveur qui fait un listen sur un socket (sock_in). Quand il recoit une demande de connection, il l'accept et crée le socket sock_out pour le traitement de la connection.

de son cote le socket client (sock_cli) est crée et se connecte à ce serveur et mon probleme survient quand je tente de fermer la socket sock_cli.

J'ai donc farfouiller pour essailller de comprendre et je me suis appercu que le sock_cli reprend la valeur du socket d'ecoute du serveur sock_in. (!). Et la je me dis que c'est normal que il y ait un segfault.

Comment cela est ce possible ? Y'a t il une methode pour y remedier ?

je suis a votre disposition pour vous montrer le code source, mais comme il est quand meme assez long je ne le ferais que si c'est necessaire...

en tout cas merci pour votre probable aide ...
  • # socket serveur / client

    Posté par  (site web personnel) . Évalué à 3.

    > la valeur du socket d'ecoute du serveur sock_in

    Pas très clair comme message ...

    Est ce que tu veut dire que la valeur de sock_cli est la meme que la valeur
    de sock_in ? C'est bien cela ?

    Dans ce cas je te rassure cela ne veut dire qu'une seule chose: l'ordre de
    creation de tes sockets dans le client et dans le serveur est le meme.
    Je parierai meme que cette valeur est 3, non ?

    Quand a ton probleme.

    1 qui fait le segfault ? (le client ou le serveur ?)
    2 si c'est le serveur que ce passe t'il si tu utilise telnet en client ?

    Sinon effectivement sans le code on ne pourra gere t'aider. (utilise pastebin ou dl.free.fr)
    • [^] # Re: socket serveur / client

      Posté par  . Évalué à 2.

      bien deviné sock_cli=sock_in et il s'agit bien de la valeur 3. :)

      1 ) c'est le client qui fait un segfault
      2 ) le client telnet se connecte bien au serveur ...

      Peut tu me detailler un peu plus ce que tu appelles l'ordre de creation de mes sockets dans le client et le serveur ?
      • [^] # Re: socket serveur / client

        Posté par  (site web personnel) . Évalué à 1.

        En fait les descripteurs de fichiers (cela inclu les sockets) sont locaux au processus en cours.
        Tout les processus ont par default 3 fd d'ouvert (0, 1 et 2) correspondant a stdin,stdout,et stderr. Si tu n'ouvre pas de fichier avant d'ouvrir ta
        socket (ou que tu les fermes avant) le fd de la socket sera le numero 3,
        si tu en ouvre une autre / un fichier il aura le numero 4 etc...

        Ces 'fd' sont des indexes sur une table au niveau kernel, donc l'ordre d'ouverture conditionne la valeur du fd.

        Bon sinon pour ton outils tu doit avoir oublié qque chose. As tu passé ton client au debugueur ?
        Que fait tu pour fermer ta socket ?
        • [^] # Re: socket serveur / client

          Posté par  . Évalué à 2.

          >En fait les descripteurs de fichiers (cela inclu les sockets) sont locaux au processus en cours.
          >Tout les processus ont par default 3 fd d'ouvert (0, 1 et 2) correspondant a stdin,stdout,et stderr. Si tu n'ouvre pas de fichier avant d'ouvrir ta
          socket (ou que tu les fermes avant) le fd de la socket sera le numero 3,
          >si tu en ouvre une autre / un fichier il aura le numero 4 etc...

          donc si je comprend bien, deux processus peuvent avoir ouvert un meme numero de socket sans pour autant, que du point de vue du systeme, ils utilisent la meme socket ... c'est bien ca ? Donc l'hypothese que j'avais émise au début n'est plus valable (cad : le client essaie de fermer le socket du serveur, donc segfault).

          je n'ai pas encore utilisé le debugger, mais ca ne va pas tarder. En fait je bosse sur d'autres problemes pour le moment...

          Pour fermer ma socket, j'utilise la meme fonction pour le client et le serveur (j'ai fait une librairie multi systeme pour les socket avec les fonction de base, dont close(...) ). Pour le serveur la fonction en question ne me sort aucun segfault et se comporte tres bien, du coté client elle plante lamentablement.... ;)

          Pour le moment je suis la .
          • [^] # Re: socket serveur / client

            Posté par  (site web personnel) . Évalué à 2.

            Pour fermer ma socket, j'utilise la meme fonction pour le client et le serveur (j'ai fait une librairie multi systeme pour les socket avec les fonction de base, dont close(...) ). Pour le serveur la fonction en question ne me sort aucun segfault et se comporte tres bien, du coté client elle plante lamentablement.... ;)

            normalement "planter" correspond à un appel mémoire incorrect (le kernel détruit ton processus car il a tenté d'accéder à un espace mémoire auquel il n'a pas accès). c'est rare que ce soit le cas avec les syscalls et impossible avec close(2). es-tu sûr que c'est sur l'appel de close ? si tu lances ton client à travers strace tu devrais voir quel est le dernier syscall avant le plantage, ça pourrat aider. si c'est un appel mémoire incorrect, lancer ton client à travers valgrind pourrait aussi grandement aider en indiquant des infos utiles de localisation du problème.
            • [^] # Re: socket serveur / client

              Posté par  . Évalué à 2.

              euuh , effectivement ... je commence à me demander si tu n'as pas raison. Je suis le deroulement de mon code pour l'instant avec des trace assez precises et j'ai l'impression d'avoir un segfault baladeur dans mon code :)...

              une fois ca tombe sur le close, une autre ca tombe un peu avant.

              je vais suivre tes conseils (strace et valgrind) pour avoir plus de precision...
              • [^] # Re: socket serveur / client

                Posté par  . Évalué à 2.

                eh be :) tu y crois ou pas :) mais je sens que je vais me faire plaisir pour le debuggage !

                le retour de strace :

                write(1, "+ 2006/05/24 17:02:10 Request st"..., 41+ 2006/05/24 17:02:10 Request state : 5.
                ) = 41
                close(3) = 0
                --- SIGSEGV (Segmentation fault) @ 0 (0) ---
                +++ killed by SIGSEGV +++
            • [^] # Re: socket serveur / client

              Posté par  . Évalué à 2.

              voici la trace valgrind de mon client :

              vex x86->IR: unhandled instruction bytes: 0x6 0x4D 0x3F 0x95
              ==15702==
              ==15702== Process terminating with default action of signal 11 (SIGSEGV)
              ==15702== Bad permissions for mapped region at address 0x8058CB5
              ==15702== at 0x4015920: ???

              bon c'est clair que ce n'est pas le socket qui plante, mais plutot le retour de la fonction...

              Si vous avez d'autre idees n'hesitez pas ...
  • # unix, udp, tcp

    Posté par  . Évalué à 2.

    Ce sont des sockets unix, tcp, ou udp, ou autre chose ?

    Quand le serveur accepte une connexion, je ne pense pas que ce soit la peine de créer une nouvelle socket. Il peut utiliser celle qu'il vient d'accepter...
    • [^] # Re: unix, udp, tcp

      Posté par  . Évalué à 2.

      multi systeme tcp .

      pour le accept : impossible, le serveur doit etre capable de gerer des connexions simultanées...
      • [^] # Re: unix, udp, tcp

        Posté par  (site web personnel) . Évalué à 3.

        pour le accept : impossible, le serveur doit etre capable de gerer des connexions simultanées...

        tu te trompes. après le succès de accept(2), tu utilises la valeur de retour comme moyen de communication avec le client qui vient de se connecter, et tu peux faire un autre accept(2) pour accepter une deuxième connexion en parallèle. pour traiter correctement en parallèle cette deuxième connexion et la communication sur la première, il te suffit de mettre tous les descripteurs nécessaires dans un fd_set à passer à select(2).

        voici un code minimaliste illustrant ça :

        -=-=---=-=---=-=---=-=---=-=---=-=---=-=--
        struct sockaddr_in client_addr;
        struct timeval tv;
        while (1) {
            int fd;
            int retval;
            fd_set conns_set;
            
            FD_ZERO(&conns_set);
            /* ... ajout des descripteurs des connexions ouvertes à conns_set ... */
            // ajout du descripteur correspondant à notre serveur
            FD_SET(tcp_server_socket, &conns_set);
            
            tv.tv_sec = 30;
            tv.tv_usec = 0;
            
            // attente d'une entrée/sortie sur un des descripteurs de conns_set
            if ((retval = select(FD_SETSIZE, &conns_set, NULL, NULL, &tv)) == -1) {
                perror("select");
                exit(-1);
            }
            
            // si select est sorti sur un timeout, rien à traiter, on boucle directement
            if (!retval)
                continue;
            
            /* ... traitement de l'input sur les descripteurs des connexions ouvertes s'ils sont toujours dans conns_set ... */
            
            // traitement d'une nouvelle connexion
            if (FD_ISSET(tcp_server_socket, &conns_set)) {
                if ((fd = accept(tcp_server_socket, (struct sockaddr *) &client_addr, (socklen_t *) &len)) == -1) {
                    perror("accept");
                    exit(-1);
                }
                
                /* ... ajouter "fd" dans la liste des descripteurs de connexions ouvertes ... */
            }
        }
        -=-=---=-=---=-=---=-=---=-=---=-=---=-=--
        • [^] # Re: unix, udp, tcp

          Posté par  . Évalué à 2.

          ouai ok :) quand tu disais creer une nouvelle chaussette, je pensais pas que tu croyais que je faisais un socket(..) apres le accept (c'est à ca que tu pensais ?).

          Je me sert effectivement du fd renvoyé par accept et je le balance dans un fd_set...

          >"il l'accept et crée le socket sock_out pour le traitement de la connection."

          effectivement je me suis plutot mal exprimée. La creation de la nouvelle chaussette se fait avec le accept...

          en fait ... tu viens grosso modo de me redonner le code que j'ai ecrit ;)
  • # MERCI :)

    Posté par  . Évalué à 2.

    merci à tous d'avoir passé un peu de temps pour m'aider ...

    j'ai reussi a trouver mon segfault (il se cachait avec des malloc mal foutu et des retours de fonctions mal faites ;). Un petit exercice qui ma remit les idees en place :)

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.