IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

MFC Discussion :

Pb de serveur avec les sockets !


Sujet :

MFC

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    227
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 227
    Points : 121
    Points
    121
    Par défaut Pb de serveur avec les sockets !
    Salut,

    Dans le problème que je vais vous énnoncer, il y a 2 programmes, le programme client et le programme serveur.

    J'avais réalisé il y maintenant presque un an, un petit tchat en c++ (DOS)
    J'essaye d'adapter le code pour le Visual c++ (Windows)

    -Dans le programme serveur*, je fait appel à la fonction "connexion(4444);" (voir ci dessous)
    * Aucun socket n'a été ouvert ou utilisé précédement dans cette application.

    -Je me connecte sur ce serveur avec le programme client (IP:127.0.0.1) et la fonction "conect()" (fonction chez le client) renvoi "0" donc la connexion a reussi.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    int connexion(const int port)
    {
       sock = socket(AF_INET, SOCK_STREAM, 0);
       sin.sin_addr.s_addr			= INADDR_ANY;
       sin.sin_family				= AF_INET;
       sin.sin_port				= htons(port);
       bind(sock, (SOCKADDR *)&sin, sizeof(sin));
       listen(sock, 0);
       ioctlsocket(sock, FIONBIO, &argp);
    }
    : Mes problèmes:

    -Pourquoi la connexion a réussi alors qu'aucune fonction "accept()" a été introduite dans le programme serveur : (par contre quant j'enleve la fonction "connexion(4444)" , la le client ne peut pas se connecter.

    -Le plus gènant c'est que la communication avec "send()" et "recv()" est impossible. (cela me parait normal vu qu'aucun socket n'a été aloué au client, c'est normalement le rôle de "accept()" )

    Merci de bien vouloir m'éclaircir sur ce problème qui me parrait un peu étrange.

    PS: J'ai essayé de me connecter sur l'ancien programme serveur (DOS) que j'avais fait et tout fonctione parfaitement il ne s'agit donc pas d'une défaillence du programme client.

    EDIT: J'utilise DevC++ (4.9.9.2)

  2. #2
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 379
    Points : 41 573
    Points
    41 573
    Par défaut
    Lorque le client cherche à se connecter, il est mis en file d'attente sur le serveur (la taille de la file d'attente est spécifiée lors de l'appel à listen()), mais il se croit connecté, même si la connexion ne sera effective que lors du accept().

    Mais tu peux tester: En théorie, avec 0 au second paramètre de listen(), un seul client peut être ainsi en attente : Si tu cherches à connecter un autre client avant que le premier soit accepté, je pense que ça devrait échouer.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    227
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 227
    Points : 121
    Points
    121
    Par défaut
    Merci pour ton explication, (moi je pensait que quant "connect()" réuississait la connexion était possible.)

    Mais il y a un truc que je comprend toujours pas, voila le partie de code qui semble poser problème (code du serveur)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    case WM_COMMAND:
     
       if(LOWORD(wParam)==1001)
          connexion(4444);
     
       if(LOWORD(wParam)==1002)
          send(csock,"coucou",7,0);
     
    return TRUE;
     
    case WM_TIMER:
     
       sinsize = sizeof(csin);
       if((csock = accept(sock, (SOCKADDR *)&csin, &sinsize)) != INVALID_SOCKET)
       send(csock, "Hello world!\r\n", 15, 0);
     
    return 0;
    Ici le client arrive à se connecter, il reçoit le message "Hello world!" mais après ceci la communication semble ne plus fonctionner car lorsque j'envoi la commande 1002 aucun message ne parvient chez le client.

  4. #4
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 379
    Points : 41 573
    Points
    41 573
    Par défaut
    Euh...

    Je te désonseille fort de mettre accept() dans un timer : C'est une fonction bloquante.

    Si tu veux jouer à ce genre de choses avec une interface graphique, tu dois tester d'abord s'il y a ou non un client à accepter. Pour cela, tu peux utiliser:
    • Soit select(), qui est plus ou moins portable
    • Soit WSAAsyncSelect() (Que j'utilise et qui est génial) ou WSAEventSelect(), fonctions qui n'existent que sous Windows (et je ne connais pas d'équivalent sous unixoïde: Je ne sais pas s'il en existe un)
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    227
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 227
    Points : 121
    Points
    121
    Par défaut
    Citation Envoyé par Médinoc
    Je te désonseille fort de mettre accept() dans un timer : C'est une fonction bloquante.
    Mais j'ai mis ça* "ioctlsocket(sock, FIONBIO, &argp);" dans la foncion "connexion()" , ça met le socket en mode non-bloquant enfin il me semble.

    * u_long argp=1;

    Comme ça il n'est pas utile de se préocuper s'il y a un client en attente ou non.

    Mais ce que je comprend pas c'est pourquoi le premier message "Hello world!" arrive à passer et que quant je clique sur le bouton (1002) aucun message ne parvient au client. :

  6. #6
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 379
    Points : 41 573
    Points
    41 573
    Par défaut
    (Ah, oui, le FIONBIO, j'avais oublié ce qu'il faisait. Généralement, je préfère utiliser WSAAsyncSelect(), alors je ne m'en sert jamais...)

    comment est déclaré csock ?


    PS: Tu es sûr que c'est bien 1002 ? Tu devrais mettre autre chose que le send (un affichage dans une editbox, etc.) pour indiquer que le clic sur le bouton est bien détecté.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    227
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 227
    Points : 121
    Points
    121
    Par défaut
    J'ai fait un truc pour voir les valeurs (int) retournées par "send();"

    "send(csock, "Hello world!\r\n", 15, 0);" retourne 15
    et
    "send(csock,"coucou",7,0);" retourne -1

    Je me demande si c'est pas la boucle des messages (boucle avec "switch(Msg)") qui bousille la liaison socket. Avec mon ancien programme serveur (DOS) je n'ai pas rencontré ce genre de PB.
    Peut c'est le fait que ce soit dans une dialogbox :

  8. #8
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    227
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 227
    Points : 121
    Points
    121
    Par défaut
    Voila le code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    #include <winsock2.h>
    #include <windows.h>
    #include <string>
     
    u_long argp=1;
       SOCKET sock, csock;
       SOCKADDR_IN sin, csin;
    int sinsize;
    char buffer[530];
     
    int connexion(const int port)
    {
       sock = socket(AF_INET, SOCK_STREAM, 0);
       sin.sin_addr.s_addr			= INADDR_ANY;
       sin.sin_family				= AF_INET;
       sin.sin_port				= htons(port);
       bind(sock, (SOCKADDR *)&sin, sizeof(sin));
       listen(sock, 0);
       ioctlsocket(sock, FIONBIO, &argp);
    }
     
    BOOL APIENTRY Dialog1Proc(HWND, UINT, WPARAM, LPARAM);
     
    int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nFunsterStil)
    {
    	DialogBox(hThisInstance,"serveur",NULL,(DLGPROC)Dialog1Proc);
    }
     
    BOOL APIENTRY Dialog1Proc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
       switch(uMsg)
       {
     
       case WM_INITDIALOG:
          SetTimer(hDlg,NULL,50,NULL);
       return TRUE;
     
       case WM_COMMAND:
          if(LOWORD(wParam)==1001)        {
          WSADATA WSAData;
          WSAStartup(MAKEWORD(2,0), &WSAData);
          connexion(4444);         }
     
          if(LOWORD(wParam)==1002)         {
          sprintf(buffer,"%d",send(csock,"coucou",7,0)); //copie la valeur retournée pat send()
          SetDlgItemText(hDlg,201,buffer);      }//affiche cette valeur
       return TRUE;
     
       case WM_TIMER:
            sinsize = sizeof(csin);
            if((csock = accept(sock, (SOCKADDR *)&csin, &sinsize)) != INVALID_SOCKET)
            sprintf(buffer,"%d",send(csock,"Hello world!\r\n",15,0)); //copie la valeur 
            SetDlgItemText(hDlg,201,buffer);  //affiche cette valeur
       return 0;
     
       case WM_CLOSE:
          PostQuitMessage(0);
       return 0;
     
       default:
       return FALSE;
     
       }
    }

  9. #9
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    35
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 35
    Points : 31
    Points
    31
    Par défaut
    il me semble que si tu ne fait pas de KillTimer, tu vas recevoir un WM_TIMER toutes les 50 ms et donc faire un accept qui va invalider ton socket...

    mais je n'en suis pas sur

  10. #10
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    227
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 227
    Points : 121
    Points
    121
    Par défaut
    Mais oui j'avais pas pensé à ça MERCI

    Et encore merci !!

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Recuper une page web "index.html" d'un serveur avec les sockets
    Par mansour67 dans le forum Développement
    Réponses: 3
    Dernier message: 18/10/2008, 13h42
  2. application client-serveur avec les sockets
    Par matheo600 dans le forum C++
    Réponses: 1
    Dernier message: 20/04/2008, 17h21
  3. communication client serveur avec les sockets
    Par timtima dans le forum Linux
    Réponses: 2
    Dernier message: 07/11/2007, 10h23
  4. application client/serveur avec les sockets
    Par baya1 dans le forum JBuilder
    Réponses: 1
    Dernier message: 24/02/2007, 15h37

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo