Partage
  • Partager sur Facebook
  • Partager sur Twitter

Les sockets

Problème de passage de chaîne

    2 juillet 2007 à 22:29:50

    Bonjour,

    j'ai créé une classe socketTCP qu'utilise un client ainsi qu'un serveur mais lors du passage d'une chaîne entre le serveur et le client je n'ai que 4caractères qui arrivent.

    Voici le fichier sockettcp.cpp

    #include "sockettcp.h"
    #include <conio.h>

    //
    //Constructeur
    socketTCP::socketTCP()
    {
            WSADATA WSAData;
       WSAStartup(MAKEWORD(2,0),&WSAData);
    /*La fonction WSAStartup sert à initialiser la bibliothèque WinSock. La macro
    MAKEWORD renseigne la bibliothèque sur la version que l'utilisateur souhaite
    utiliser (ici la version 2). Elle retourne la valeur 0 si tout s'est bien passé.
    */

    }

    //
    //Destructeur
    socketTCP::~socketTCP()
    {
            WSACleanup();
    /*Cette fonction va simplement libérer les ressources allouées par la fonction
    WSAStartup().*/

    }

    //
    //initialisation de la socket
    socketTCP::initialisation()
    {
       sock = socket(AF_INET,SOCK_STREAM,0);
       if(sock < 0) sock = -10;
       return(sock);
    /*int socket(int domain, int type, int protocol)
    Le paramètre domain représente la famille de protocoles utilisée.
    Il prend la valeur AF_INET pour TCP/IP.

    Le type indique le type de service, il peut avoir les valeurs suivantes :
    SOCK_STREAM, si on utilise le protocole TCP/IP.
    SOCK_DGRAM, si on utilise le protocole UDP/IP.

    Dans le cas de la suite TCP/IP, le paramètre protocol n'est pas utile,
    on le mettra ainsi toujours à 0.*/

    }

    //
    ////Etablissement d'une connexion avec le client
    socketTCP::attenteConnexion()
    {
     int test;

     //configuration du serveur
     sin.sin_addr.s_addr = htonl(INADDR_ANY);
     sin.sin_family = AF_INET;
     sin.sin_port = htons (1500);

    /*sin.sin_addr.s_addr sera l'IP donnée automatiquement au serveur.
    Pour le connaître nous utiliserons la fonction htonl avec comme seul paramètre
    la valeur INADDR_ANY.
    Si vous voulez spécifier une adresse IP precise à utiliser, il est possible
    d'utiliser la fonction inet_addr() avec comme seul paramètre l'IP dans une
    chaine de caractères :

    Code : Cinet_addr("127.0.0.1");

    sin.sin_family sera toujours égal à AF_INET dans notre cas (en savoir plus).
    Et sin.sin_port sera égal à la valeur retournée par la fonction htons, avec
    comme paramètre le port utilisé.
    */



            test = bind (sock, (SOCKADDR *) &sin, sizeof sin);
       if(test == SOCKET_ERROR) test = -11;
    /*Voilà ! Maintenant que toutes les informations sont données, il va falloir
    mettre la socket dans un état d'écoute*/

       else
       {
            test = listen(sock, 5);
          if(test == SOCKET_ERROR) test = -12;
    /*La fonction retourne SOCKET_ERROR si une erreur est survenue.
    Le paramètre sock désigne la socket qui va être utilisée.
    Le paramètre 5 représente le nombre maximal de connexions pouvant être
    mises en attente. */


          else
          {
            taille = (int) sizeof(sin);
            sock = accept (sock, (SOCKADDR *) &sin, &taille);
            if(sock == INVALID_SOCKET) test = -13;
    /*Cette fonction permet la connexion entre le client et le serveur en acceptant
     un appel de connexion.

    La fonction retourne la valeur INVALID_SOCKET en cas d'échec.
    Le paramètre socket est, comme dans les autre fonctions, la socket utilisée.
    Le paramètre addr ne s'utilise pas comme dans la fonction bind ; ici, il faut
    créer une variable taille, égale à la taille de la structure qui contient les
    informations pour la connexion... Ensuite, il faudra passer l'adresse de cette
    variable en paramètre.
    De même pour le paramètre addrlen, c'est-à-dire la taille de la structure qui
    contient les informations sur la connexion. */

                            else
             {
              test = 1;
             }
          }
       }
    return (test);
    }

    //
    //fermeture de la socket
    socketTCP::fermer()
    {
            int test;
       test = closesocket(sock);
       if(test < 0)test = -14;
       else test = 1;
       return(test);
    }


    //
    //connexion au serveur
    socketTCP::connexion(char* adrIP)
    {
            int test;
       //configuration de la connexion
       sin.sin_family = AF_INET;
       sin.sin_port = htons(1500);
       sin.sin_addr.s_addr = inet_addr(adrIP);

       test = connect(sock, (SOCKADDR *)&sin, sizeof(sin));
       if(test < 0) test = -15;
       else test = 1;
       return(test);
    }

    //
    //envoyer une chaîne de caractère
    socketTCP::envoyer(char* buffer)
    {
            int test;
       test = send(sock, buffer, sizeof(buffer),0);
       if(test == SOCKET_ERROR) test = -16;
       else test = 1;
       return(test);
    }

    //
    //recevoir une chaîne
    socketTCP::recevoir(char *buffer)
    {
            int test;
       test = recv(sock, buffer, sizeof(buffer), 0);
       if(test == SOCKET_ERROR) test = -17;
       else{ test = 1;printf("\n------------>%s\n", buffer)}
       return(test);
    }

    //
    //shutdown
    socketTCP::shut()
    {
            shutdown (sock, 2);
    }


    Voici le fichier sockettcp.h


    #include <winsock2.h>
    #include <stdio.h>
    #include <stdlib.h>

    class socketTCP
    {
     public:
     //les variables
     int sock,taille;
     SOCKADDR_IN sin;
     hostent *hp;
     char buffer[1024];

     //Constructeur
     socketTCP();

     //Destructeur
     ~socketTCP();

     //Initialisation de la socket
     int initialisation();

     //Etablissement une connexion avec le client
     int attenteConnexion();

     //fermer la socket
     int fermer();

     //connexion au serveur
     int connexion(char* adrIP);

     //envoyer une chaîne de caractère
     int envoyer(char* buffer);

     //recevoir une chaîne de caractère
     int recevoir(char *buffer) ;

     //shutdown
     shut();
    };
     


    Voici le client.cpp

    #include "socketTCP.h"
    #include <stdio.h>
    #include <conio.h>
    #include <stdlib.h>

    int main(void)
    {
            socketTCP csocket;
            int val_rep;
       char adrIP[16];
       char message[1024];

            //initialisation de la socket
            val_rep = csocket.initialisation();
       if(val_rep == -10)
            printf("erreur d initialisation");
       else
       {
            printf("Entrez l adresse IP de l'ordinateur serveur\n");
          scanf("%s",adrIP);
         
            //connexion a la socket
          val_rep = csocket.connexion(adrIP);
          if(val_rep == -16)
            printf("erreur de connexion");
          else
          {
            printf("connexion etablie avec le client\n");
             printf("Attente de la reponse");
             val_rep = csocket.recevoir(message);
             if(val_rep == -17)
                    printf("erreur pendant la reception du message");
             else
                {
                           printf("%s",message);
                           csocket.fermer();
                   getch();
                }

          }
       }

    }
     


    le serveur.cpp

    #include "socketTCP.h"
    #include <stdio.h>
    #include <stdlib.h>
    #include <conio.h>

    int main(void)
    {
       //agrégation par valeur de la classe socketTCP
            socketTCP ssocket;
       int val_rep;
       char message[512];
       //initialisation de la socket
       val_rep = ssocket.initialisation();
       if(val_rep == -10)
            printf("initialisation de la socket incorecte");
       else
       {
            printf("La socket est maintenant ouverte en mode TCP/IP\n");
          printf("Patientez pendant que le client se connecte\n");
          //étape:  bind listen accept
          val_rep = ssocket.attenteConnexion();
          if(val_rep == -11)
            printf("erreur de bind");
          if(val_rep == -12)
            printf("erreur de listen");
          if(val_rep == -13)
            printf("erreur d accept");
          else
          {
            printf("Un client est connecte\n");
             printf("Entrez votre message:\n");
             scanf("%s",message);
             val_rep = ssocket.envoyer(message);
                    if(val_rep == -16)
                {
                           printf("erreur pendant l'envoi du message");
                   getch();
                }
             else
             {
                    printf("Votre message est envoye");
                ssocket.fermer();
                getch();
             }
          }
       }

    }
     


    En espérant que vous puissiez me venir en aide je vous souhaite une agréable journée, soirée ou encore nuit! :D
    • Partager sur Facebook
    • Partager sur Twitter
      2 juillet 2007 à 22:35:59

      MONSTRUOSITE DETECTED

      printf("erreur de bind");
      //Et il n'est pas seul
       

      MONSTRUOSITE DETECTED


      Déjà réécris ton code 100% C++. Parce qu'on s'y retrouve plus.
      • Partager sur Facebook
      • Partager sur Twitter
        3 juillet 2007 à 10:25:22

        Tu peux dire ce que tu veux mais ce n'est pas interdit, je ne suis pas très "cin ou cout", bref les classe c'est du langage objet donc c++ c'est pourquoi j'ai posté ici.
        Mais je ne demande pas de critique mais plus une aide! parceque c'est bien beau de critiqué mais sais-tu seulement en faire autant. :(
        A bientôt ;)
        • Partager sur Facebook
        • Partager sur Twitter
          3 juillet 2007 à 10:52:06

          J'ai aussi une question, c'est quoi sa?
          socketTCP::fermer()
          {
                  int test;
             test = closesocket(sock);
             if(test < 0)test = -14;
             else test = 1;
             return(test);
          }


          Ca devrait pas plutot être :
          int socketTCP::fermer()//le int?
          {
                  int test;
             test = closesocket(sock);
             if(test < 0)test = -14;
             else test = 1;
             return(test);
          }
          • Partager sur Facebook
          • Partager sur Twitter
            3 juillet 2007 à 11:45:23

            Regarde ce que te retournent les primitives "send" et "recv". Normalement, elle renvoient le nombre de bytes recu/envoyé, et le maximum pratique doit se situer autour des 1500 bytes par packet. Si tu veux envoyer plus, tu dois te débrouiller par envoyer en plusieurs fois. Mais avec une vingtaine de caractères, tu devrais pas avoir de problème, pourtant. Sinon, <unixoide = on> lorsque la connection est fermée, la "recv" retourne immédiatement, avec le code d'erreur -1. Par contre, si tu essayes d'envoyer des données avec "send" sur un socket dont la connection est fermée, aucun code d'erreur n'est renvoyé: ton programme reçoit un signal du système, et si tu le gères pas, il se ferme sans que tu comprennes pourquoi.

            Sinon, comme le suggère Gogeta1, quitte à faire du C++, fais-en pas juste à moitié. Et les cin/cout, je peux t'assurer que c'est 1000x moins la prise de tête que les print* et compagnie. (Et ca fait moins de caractères à tapper.) Et en plus, ça fait vraiment tache, dans un joli code en C++...

            Ah, autre chose: pour la gestion des erreurs, au lieu de transformer ce que te renvoie les primitives en un code d'erreur perso un peu louche, utilise ce qui est prévu pour ça en C++: Les exceptions.. (si tu connais, sinon, tu pourras toujours adapter ton code plus tard.)

            A part ça, je sais pas comment c'est possible, mais ton code ne devrait pas compiler.. Pour commancer, essaye d'appeler g++ avec "-ansi -pedantic -Wall". Normalement, avec ton code, tu devrais au moins pouvoir générer l'équivalent de la bible en warning..
            • Partager sur Facebook
            • Partager sur Twitter
              3 juillet 2007 à 11:56:00

              Euh gogeta regarde le .h avant de dire des bêtises la méthode y est déclaré, après si je compile comme tu le dis vive les erreurs :p

              Merci Gravstein pour la proposition d'exeption, mais par la suite j'aurai besoin de ces erreurs, sinon, il n'y a pas de problème à par qu''à la connection de mon client sur mon serveur, le serveur demande à l'utilisateur d'entrer un message à transmettre au client, mais le client ne reçoit que 4 caractère et aprè de longues heures de recherche... :'(
              • Partager sur Facebook
              • Partager sur Twitter
                3 juillet 2007 à 14:07:37

                Gogeta a tout à fait raison, en ce qui concerne les types de retour dans la définition des méthode: il doit aussi être mentionné! Regarde le cours de Matéo, t'as du zapper l'épisode.

                De plus,

                class X
                {
                //[...]
                shut(); //<- ca!!
                };
                 

                Ca n'est ABSOLUMENT pas autorisé. C'est du C++, pas du C: il n'y a pas de type de retour implicite (int). Seuls les constructeurs et destructeurs ont le droit (l'obligation, même) de n'avoir aucun type de retour, de par leurs nature.

                Je comprends toujours pas comment ça peut compiler.. Même sans aucun flags..
                Sinon, pour les exceptions, ça reste toujours plus puissant, plus souple et plus propre que d'utiliser des valeurs de retour pour propager des status d'erreur. Et tu peux toujours utiliser la valeur de l'objet lancé (throw).
                • Partager sur Facebook
                • Partager sur Twitter
                  3 juillet 2007 à 18:12:55

                  sauf que la méthode shut ne retourne rien donc à la régueur je peux mettre un void devant pour vous faire plaisir ^^
                  Sinon toutes les méthodes retournant quelque chose sont spécifier dans le .h ;)
                  • Partager sur Facebook
                  • Partager sur Twitter
                    3 juillet 2007 à 23:38:36

                    Non, mais tu le fais exprès, ou t'as rien compris?
                    Un language de programmation, c'est quelque chose de formel, une syntaxe stricte, des règles sans ambiguïtés, etc! Et tu DOIS respecter ces règles, sous peine de produire un executable instable et imprévisible dans le meilleurs des cas (les plus rares), ou tout simplement reçevoir des insultes de la part du compilateur dans la plupart des cas.

                    Maintenant, soit tu codes en C++ et on peut essayer de t'aider, sinon ben.. tu trouves quelqu'un d'autre que moi, si tu veux pas y mettre un peu de bonne volonté.
                    • Partager sur Facebook
                    • Partager sur Twitter
                      4 juillet 2007 à 10:35:54

                      Bas je crois que je vais allez voir ailleur merci quand même!
                      Pour info mes déclarations de méthodes sont bonnes j'aivais juste besoin d'information sur le send et le receve des sockets. Et les printf ne sont là que pour vérifier le bon fonctionnement et vont disparaître. Maintenant si tu te fis qu'aux court de Mateo tu risque d'avoir des surprises quand tu devras créer étudier des gros codes même utiliser une documentation, si mon code compile sous 3 compilateur différents c'est qu' il doit pas être si faux :-°
                      • Partager sur Facebook
                      • Partager sur Twitter

                      Les sockets

                      × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                      × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                      • Editeur
                      • Markdown