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

wxWidgets Discussion :

Problème de comportement des sockets


Sujet :

wxWidgets

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 66
    Points : 44
    Points
    44
    Par défaut Problème de comportement des sockets
    Bonjour,

    Je suis en train de construire une architecture distribuée constituée de trois process, A, B et C.

    B et C communiquent à l’aide de sockets, B étant client et C serveur.

    A et C sont lancés de manière autonome, et sont donc commandés à l’aide d’une interface (GUI)
    B est créé et lancé par A. A et B communiquent par pipe.

    Autrement dit, C est une ressource distante. A est un processus maître qui lance localement des processus de type B qui ont besoin d’utiliser la ressource distante C.

    Pour construire cette architecture, je commence par construire la relation entre B et C, et par tester cette relation, en lançant B de manière autonome (avec une interface).

    Je construis la communication par sockets entre B et C, en partant de l’exemple « client-server » intégré à wxWidgets (wxWidgets\samples\sockets\).

    Dans cet exemple,

    Côté server :

    - Dans le constructeur de MyFrame :
    o Un nouvel objet, m_server, de classe wxSocketServer, est créé, et associé à l’adresse 3000 (port).
    o Un EventHandler est associé à m_server : (MyFrame, SERVER_ID)
    o Le filtre d’évènements est limité à wxSOCKET_CONNECTION_FLAG
    - Dans la table d’évènements de MyFrame, SERVER_ID est associé à la méthode « MyFrame ::OnServerEvent(…event) »
    - MyFrame ::OnServerEvent(…event)
    o Cette méthode ne peut donc à priori être lancée que par un évènement de type « CONNECTION ». Elle est donc exécutée lorsque le client envoie une commande « Connect », vers la socket server.
    o Cette méthode lance l’exécution de la fonction Accept() de m_server, et crée une wxSocketBase, sock, associée à la relation entre le server et le client qui vient de se connecter.
    o Ensuite, un EventHandler est associé à sock, (MyFrame, SOCKET_ID).
    o Le filtre d’évènements est alors établi à « INPUT » | « LOST »

    Côté client :

    - Dans le constructeur de MyFrame :
    o Un nouvel objet, m_sock, de classe wxSocketClient() est créé.
    o Un EventHandler lui est associé : (MyFrame, SOCKET_ID)
    o Le filtre d’évènements est établi à : « CONNECTION »|« INPUT »|« LOST »
    - Dans la table d’évènements de MyFrame :
    o SOCKET_ID est associé à MyFrame ::OnSocketEvent
    o Un évènement « Menu », CLIENT_OPEN, est associé à MyFrame ::OnOpenConnection()
    - MyFrame ::OnOpenConnection(…event) :
    o Dans le mode normal, proposé par l’exemple, le processus client est commandé par une interface. C’est donc la commande « OpenSession » de cet interface, qui entraîne l’exécution de OnOpenConnection(…event).
    o Exécute la fonction Connect sur m_sock, avec comme paramètres :
     Une adresse composé de « adresse IP4 du server » + 3000 (port)
     « false » : ce qui signifie que l’appel Connect est en mode « non bloquant ». Autrement dit, la fonction Connect n’empêche pas l’exécution du thread principal du client, qui se poursuit sans attendre la réponse du server
    o La fonction Connect étant lancée en monde non-bloquant, en général, le thread principal poursuit son exécution, sans que la connexion soit valide (du moins du côté client). C’est sans doute pourquoi le concepteur du programme a fait suivre la fonction Connect de la fonction WaitOnConnect(time_out).
    o La fonction WaitOnConnect renvoie :
     « true », soit si la connexion avec le server est établie correctement, soit si le server est inaccessible.
     « false » en cas de dépassement du time_out.
    o Si le time_out est bien réglé, dans le cas général, le server étant présent, la fonction WaitOnConnect renvoie true, et la connexion est établie correctement.

    Mes problèmes commencent lorsque je veux exécuter exactement la même suite de fonctions, mais à partir de A, B n’étant plus lancée en mode autonome, mais étant créé par A. Pour clarifier le débat, donnons deux noms différents à ces deux modes d’exécution de la liaison B-C :
    - mode « autonome » dans le cas où B est lancé de manière autonome, et dispose de son propre interface.
    - Mode « commandé » dans le cas où B est créé et lancé par A.

    Si je laisse le paramètre de blocage de Connect à false, le thread principal se poursuit, dans le cas commandé, exactement comme dans le cas autonome, c’est-à-dire que l’on ressort de la fonction Connect, dans un état « non-connecté ».

    La différence est maintenant que, en mode commandé, le process B reste bloqué dans la fonction WaitOnConnect, tandis qu’en mode autonome, il ne reste pas bloqué dans cette fonction.

    J’ai réussi à résoudre ce premier problème, dans le mode commandé, en mettant le paramètre de blocage de Connect, à « true ». En mode commandé, la fonction Connect ressort alors avec une connexion valide, et je n’ai plus besoin de la fonction WaitOnConnect, que je supprime donc.

    Je suis alors tombé sur un deuxième problème : la première instruction Write, à l’aide de laquelle le process client était censé envoyer un message au server, est restée dans un état bloqué.

    J’ai réussi à résoudre ce problème, à l’aide de l’instruction :

    m_sock->SetFlags(wxSOCKET_NOWAIT)

    placée avant Write.


    J’ai donc maintenant une architecture générale qui fonctionne, mais je reste insatisfait, parce que je ne comprends pas bien, en profondeur, comment elle fonctionne. J’aimerais savoir si quelqu’un pourrait m’expliquer les raisons de la suite de fonctionnements et dysfonctionnements que j’ai constatés. Je suspecte une sorte d’interférence entre les sockets et le système de gestion des évènements. J’imagine que dans le mode autonome, le thread principal, dès qu’il a fini d’exécuter les tâches demandées par le programmeur, retourne dans une sorte de boucle dans laquelle il attend les évènements. Tandis qu’en mode commandé, ce n’est peut-être pas le cas. Cela signifierait que la fonction WaitOnConnect, à la différence de la fonction Connect, se branche sur la boucle de lecture des évènements. Si cette boucle pour une raison ou pour une autre, ne fonctionne pas, la fonction WaitOnConnect(), dans le mode commandé, bouclerait indéfiniment. Ceci qui expliquerait la différence de comportement entre les deux modes…


    Zorglbug

  2. #2
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Bonjour,
    On parle bien de 2 process : il n'y a pas de mutli thread dans aucun des cas ?
    Sinon, quelques pistes : peut-il y avoir un risque de blocage dans la synchro entre les 2 process A et B? Peux-tu tracer les demandes de connexions côté serveur pour voir si dans les deux cas elles sont à peu près synchrones (tester si le blocage est bien au niveau de l'attente de la confirmation de la connexion). Enfin, en lieu et place de WaitOnConnect, tu peux trapper l'évènement wxSOCKET_CONNECTION (ou wxSOCKET_LOST ).
    Enfin, pour enrichir le forum, tous tes retours seront très très intéressants. Merci de nous tenir informé. Accessoirement, si tu peux poster du code...

    EDIT: Pour ma culture perso, wxWidget c'est pour des cours ? des projets perso ? En entreprise ?

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 66
    Points : 44
    Points
    44
    Par défaut
    > On parle bien de 2 process : il n'y a pas de mutli thread dans aucun des cas :

    Oui, A B et C sont bien des process séparés, pas des threads d'un même process.

    >Peux-tu tracer les demandes de connexions côté serveur pour voir si dans les deux cas elles sont à peu près synchrones

    Oui, j'ai tout tracé, j'ai fait un dump de tous les échanges dans un unique fichier, pour bien visualiser les échanges et leur séquencement.

    > Enfin, en lieu et place de WaitOnConnect, tu peux trapper l'évènement wxSOCKET_CONNECTION (ou wxSOCKET_LOST ).

    Effectivement, c'est une méthode que je n'ai pas encore testé.

    > Enfin, pour enrichir le forum, tous tes retours seront très très intéressants. Merci de nous tenir informé. :

    oui oui, je le ferai. J'ai été énormément aidé sur ce forum, mais je conçois bien que c'est un lieu d'échange, et que, si je le peux, je dois aussi apporter ma brique.

    > Pour ma culture perso, wxWidget c'est pour des cours ? des projets perso ? En entreprise ?

    Projet perso ...

    Dans la mesure où j'obtiendrai des clés de compréhension de ce qui se passe dans cette architecture, je les noterai sur ce fil,

    Cordialement,

    zorglbug

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 66
    Points : 44
    Points
    44
    Par défaut
    Bonsoir,

    J'ai fait des essais en "trappant" l'évènement wxSOCKET_CONNECTION : ça marche en mode commandé comme en mode autonome :

    on peut placer la fonction Connect(... false) (mode non bloquant) dans une fonction F qui ressort tandis que la connection n'est toujours pas établie : le serveur a reçu un évènement qui lui fait lancer la fonction Accept, mais au moment où le client ressort de la fonction F, celui-ci est toujours en mode "non connecté".

    Ensuite, quelques temps plus tard, le client reçoit du serveur l'évènement de type "wxSOCKET_CONNECTION ", et à ce moment là, il passe bien en mode connecté.

    Du coup, je commence à suspecter de plus en plus la fonction WaitOnComment().

    cordialement,

    Zorglbug

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 66
    Points : 44
    Points
    44
    Par défaut
    Bonsoir,

    je voulais dire "WaitOnConnect", et pas "WaitOnComment".

    Après plusieurs manips, je pense avoir la réponse définitive au problème :

    La différence vient du fait qu'en mode commandé, j'ai placé toutes les fonction de connection et d'échange de données (Read et Write), dans wxApp::OnInit().

    Tout ce que j'ai pu observer comme mauvais et bons fonctionnements, peut s'expliquer de la façon suivante (je ne prétends pas que ce soit la bonne explication) :

    - Les fonctions comme Read, Write, WaitOnConnect, etc... utilisent la boucle d'évènements.

    - Le programme principal ne lance cette boucle qu'après avoir fini d'exécuter "wxApp::OnInit()".

    Par conséquent, quand ces fonctions (Read, Write, etc...) sont placées dans le wxApp::OnInit, la boucle d'évènement n'existe pas, et elles restent dans un état bloqué.

    Cordialement,

    zorglbug

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 66
    Points : 44
    Points
    44
    Par défaut
    Bonsoir,


    bon, voilà, j'ai fait des tests vraiment exhaustifs du système à trois process communicant par deux jeux de sockets client-serveur. Tout fonctionne bien. C'était donc bien un problème de "deadlock" dû au fait que les fonction Read, Write et WaitOnConnect doivent nécessiter la présence de la boucle d'évènements.

    Maintenant, je peux considérer mon problème comme résolu.

    Merci bien !

    Cordialement,

    Zorglbug

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

Discussions similaires

  1. Réponses: 0
    Dernier message: 18/12/2011, 14h13
  2. Réponses: 3
    Dernier message: 27/10/2008, 22h31
  3. Réponses: 1
    Dernier message: 14/03/2007, 07h25
  4. [Coldfusion] Problème de comportement des *.cfm
    Par DarkOcean dans le forum Coldfusion
    Réponses: 7
    Dernier message: 21/06/2006, 18h52
  5. problème avec des sockets
    Par ddii dans le forum Réseau
    Réponses: 10
    Dernier message: 15/11/2005, 15h53

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