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

Qt Discussion :

[Avis] Réalisation d'un "routeur" pour rediriger des trames à une fenêtre précise


Sujet :

Qt

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre expérimenté Avatar de MacPro
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    367
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Novembre 2007
    Messages : 367
    Par défaut [Avis] Réalisation d'un "routeur" pour rediriger des trames à une fenêtre précise
    Bonjour,

    ma question n'a probablement pas sa place ici, mais vu que j'aime bien le forum

    En fait, je sollicite votre aide/vos idées pour un point de mon programme qui me chagrine.

    Je vous exlique le schmilblik :

    • J'ai une application Qt qui sert d'IHM client pour interfacer une machine
    • La machine est branchée à un serveur (pas fait avec Qt) dont le développement est effectué par un collègue.
    • depuis l'IHM je peux demander tout un tas d'actions différentes à la machine, certaines étant bloquantes, d'autres non, ça dépend du temps que ça prend.

    Exemple : 2 actions :
    1. allumer la lumière (très rapide)
    2. faire tourner les moteurs pendant un certain temps (un certain temps )



    voilà, le contexte étant posé, je décris brièvement comment se passe une action :
    • Chaque action particulière est effectuée depuis une fenêtre associée.
    • je clique sur menu>lumière, une nouvelle fenêtre avec des paramètres variés (comme la lumière à activer, puissance ...) apparaît.
    • Sur cette même fenêtre, j'ai un QTextEdit, qui sert de 'log' (ex. : "commande envoyée", "commande refusée" ...).
    • Je fais mes réglages et je clique "envoyer demande", la trame de commande par au serveur, qui dans ce cas (lumière) me répond instantannément, du coup j'affiche dans le log ce que répond le serveur (un "acknowledge" pour le moment).


    Le problème :
    • pour une action plus longue (les moteurs), le serveur acknowledges tout de suite, et l'action s'effectue dans un thread au niveau du serveur.
    • moi, je veux fermer ma fenêtre et pouvoir faire autre chose en attendant.
    • J'aimerais que - lorsque le serveur a fini - il envoie une trame contenant un message, et que le fameux routeur sache à quelle fenêtre de mon programme rediriger ce message. La fenêtre en question se contentera d'ajouter le message dans le log, même si elle n'est pas en avant plan.



    voilà donc en résumé mon problème avec quelques précisions :
    • la classe contenant les objets de communication (un pour envoyer et un pour recevoir) est à instance unique (j'ai pas encore de singleton, pour le moment, je sais que je ne fais qu'une instance, et je véhicule le pointeur aux classes qui en ont besoin (c'est crade je sais ))
    • Rediriger une trame à un destinataire précis (souvent une fenêtre)


    Mes pistes :
    • L'application instancie la communication, avec le QTcpSocket pour envoyer, et le QTcpServer pour recevoir.
    • Chaque nouvelle classe (dialogue ou fenêtre la plupart du temps) susceptible de recevoir des informations provenant du serveur demande à l'application de l'ajouter dans une liste d'éléments communiquants en lui fournissant un identifiant unique (pourquoi pas la valeur de son pointeur this).
    • Ensuite, chaque fois qu'une fenêtre communiquante envoie une requête, elle joint son identifiant dans la trame pour que le serveur puisse remettre cet ID dans sa trame de réponse plus tard.
    • Lors d'une réponse, l'application examine l'ID dans la trame, et envoie un signal à l'objet @ID avec le contenu de la trame.


    Comment pourrais-je faire ça au mieux, en evitant que chaque fenêtre/dialogue ne s'amuse à vérifier si le message lui est bien destiné ?

    voilà, merci pour ceux qui ont lu jusque là ou même rien que jusqu'à la moitié

  2. #2
    Membre émérite

    Profil pro
    Inscrit en
    Mai 2007
    Messages
    774
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Mai 2007
    Messages : 774
    Par défaut
    Salut,

    Selon moi, je pense que les pistes que tu as évoquées sont les bonnes, à savoir faire correspondre un ID à une tâche, ou à l'objet "émetteur".

    Cependant, il ya quelque chose que je ne comprends pas dans ta question finale
    Comment pourrais-je faire ça au mieux, en evitant que chaque fenêtre/dialogue ne s'amuse à vérifier si le message lui est bien destiné ?
    Cela signifie que chaque objet/fenêtre contient son propre moyen de communication avec le serveur (à savoir QTcpSocket/Server) ?

    G.

  3. #3
    Membre expérimenté Avatar de MacPro
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    367
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Novembre 2007
    Messages : 367
    Par défaut
    Salut,

    d'abord d'avoir lu !

    la fin de mon post est un peu bordélique, j'ai quelques soucis pour exprimer mes pensées parfois ? Chaque object ne possède pas de QTcpSocket ou QTcpServer, néanmoins, ils possèdent tous un pointeur vers le QTcpSocket, ce qui leur permet d'envoyer des données.

    Vu que je débarquais un peu dans l'info, j'ai fait ça un peu à l'arrache, je ne connaissais pas les singleton, c'est pourquoi, chaque objet possède un constructeur dans à qui l'application qui se charge de l'instancier lui file en paramètre le pointeur vers l'unique instance de la classe de communication (qui contient deux QTcpSocket et un seul QTcpServer).

    pour reprendre :

    Comment pourrais-je faire ça au mieux, en evitant que chaque fenêtre/dialogue ne s'amuse à vérifier si le message lui est bien destiné ?
    en essayant de formuler autrement, lorsque le QTcpServer reçoit une trame, je ne veux pas qu'il émettre un signal à tous les objets, chacun d'eux se chargerait alors de regarder si le message lui est destiné. je préfererais que l'application aille regarder dans une sorte de table de routage pour rediriger la trame au bon objet, c'est plus clair ou toujours confu ?

  4. #4
    Alp
    Alp est déconnecté
    Expert confirmé

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par défaut
    Alors, je verrais bien le truc suivant : quand tu envoies une commande, bim la fenêtre se ferme. Dans la trame envoyée, il est clair que tu demandes de la lumière ou de faire tourner les moteurs par ex, on est d'accord ?

    Ensuite, le serveur répond quelque chose, qui se rapporte à ce que tu as demandé. Alors personnellement, je verrai bien une map ou autre qui relierait une "commande" (lumière, moteurs, café, ...) à une fenêtre.
    Ainsi, lorsque le signal de reception est émis par la classe communiquante, tu le lies à un slot dans ta fenêtre principale qui permet de transmettre le message reçu à la bonne fenêtre, en émitant un signal de cette fenêtre, auquel serait associé un slot de ce même fenêtre, qui permettrait de récupérer le contenu envoyé par le serveur, de le parser et de l'afficher.

    Qu'en dis-tu ?

  5. #5
    Membre émérite

    Profil pro
    Inscrit en
    Mai 2007
    Messages
    774
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Mai 2007
    Messages : 774
    Par défaut
    Ah d'accord !

    Je suppose qu'à l'heure actuelle, dans ton "objet qui communique", tu gardes à chaque fois une référence sur la dernière fenêtre appelante, pour ainsi savoir à qui tu renvoies le message, c'est cela ?

    Pour ma part, ayant grossièrement la même application(une IHM qui commande à "un truc qui communique"), mon architecture ressemble à ça.

    1 - Une IHM, qui n'a aucune référence sur "le truc qui communique", qui émet des signaux quand l'utilisateur fait des choix, et qui a des slots pour mettre à jour l'affichage.

    2 - Mon "truc qui communique", sans référence sur l'IHM, qui a des slots pour adapter sa communication aux choix de l'utilisateur, et des signaux qui, quand je recois des messages, émettent les "nouvelles" à l'IHM.

    3 - Un Controler, qui a une référence sur l'IHM et une référence sur le truc qui communique, et dans lequel je fais tous les connect(signaux/slots) entre l'IHM et le "truc qui communique".

    Je ne suis pas non plus très éxpérimenté en conception/architecture logicielle, mais cette architecture me permet au moins de pouvoir modifier l'un ou l'autre des éléments, sans avoir à toucher l'autre.

    Pour ton cas, si tu ne veux/peux pas modifier l'architecture de ton programme, je pense que le mieux a faire est de faire une classe ayant une référence sur toutes tes fenêtres, avec un slot connecté au "QTcpServer". Ainsi ton server enverra le signal avec l'ID à ce nouvelle classe, qui, en lisant l'ID, émettra un signal à la fenêtre concerné.

    Enfin, cela reste uniquement mon point de vue.

    Bonne chance,

    G.

  6. #6
    Membre expérimenté Avatar de MacPro
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    367
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Novembre 2007
    Messages : 367
    Par défaut
    Ainsi, lorsque le signal de reception est émis par la classe communiquante, tu le lies à un slot dans ta fenêtre principale qui permet de transmettre le message reçu à la bonne fenêtre, en émitant un signal de cette fenêtre, auquel serait associé un slot de ce même fenêtre, qui permettrait de récupérer le contenu envoyé par le serveur, de le parser et de l'afficher.

    Qu'en dis-tu ?
    Salut, merci à toi aussi.
    Oui, c'est bien mon idée, pour l'instant c'est l'application qui gère les messages entrants. Dans mon programme, il y a une partie en dur (le mainform par exemple), et pour le moment je ne fais transmets des informations qu'à ce mainform.
    le plus gênant, c'est que de temps à autre, le serveur peut être coupé, ou la configuration de la machine peut changer. Si par exemple, une personne vient ajouter un moteur, le serveur s'en rend compte, et le client doit alors signaler à certains objets qu'une mise à jour est à faire.
    exemple :
    J'ai une entrée de menu : menu > demarrer/arreter les moteurs puis des sous menus avec un numéro de moteur, donc menu > demarrer/arreter > moteur n°i.
    En cliquant sur le sous menu, j'obtiens une fenêtre de type dialogue, sur laquelle j'ai des widgets, comme la vitesse, le sens de rotation, .... et un log.
    Si la connexion vient à être coupée on si on modifie le nombre ou le type des moteurs, là, on détruit proprement toutes les instances des fenêtres de dialogues liées aux moteurs, ainsi que les sous menus. Il faudrait aussi aller dire au "routeur" que le dialogue va partir, et qu'il faut l'enlever de sa table de routage (donc faire des éventuelles déconnexions de signaux ?)
    Lorsque la connexion revient, on regarde la configuration système (nombre et type des moteurs), et on construit les dialogues associés. Chaque nouveau dialogue vient alors s'enregistrer dans la "table de routage", et donc l'application s'occupera d'emettre un signal au bon destinataire avec le contenu de la trame.

    ... je me rends compte qu'en expliquant ... je m'explique à moi même et la solution semble approcher.

  7. #7
    Membre expérimenté Avatar de MacPro
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    367
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Novembre 2007
    Messages : 367
    Par défaut
    Je suppose qu'à l'heure actuelle, dans ton "objet qui communique", tu gardes à chaque fois une référence sur la dernière fenêtre appelante, pour ainsi savoir à qui tu renvoies le message, c'est cela ?
    Non, car si on lance une action qui prend une minute, on ferme la fenêtre, on lance une autre qui prend 10 secondes ... là ça coincerait.

    Je ne suis pas non plus très éxpérimenté en conception/architecture logicielle, mais cette architecture me permet au moins de pouvoir modifier l'un ou l'autre des éléments, sans avoir à toucher l'autre.
    moi non plus

    Pour ton cas, si tu ne veux/peux pas modifier l'architecture de ton programme, je pense que le mieux a faire est de faire une classe ayant une référence sur toutes tes fenêtres, avec un slot connecté au "QTcpServer". Ainsi ton server enverra le signal avec l'ID à ce nouvelle classe, qui, en lisant l'ID, émettra un signal à la fenêtre concerné.
    ouais, j'étais en train de me dire que je pourrais essayer de faire une classe mère dont chaque objet communiquant hériterait. Cette classe de base s'occuperait de s'enregistrer/se retirer à/de la table de routage (cf. mon post précédent) ... c'est une mauvaise idée ?

  8. #8
    Membre éclairé

    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Février 2005
    Messages
    464
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2005
    Messages : 464
    Par défaut
    Tu souhaites généraliser ton problème de log à la réception non synchronisée d'une réponse du serveur à une requête client.

    Tu as :
    • Ton application qui reçoit tous les messages serveur
    • Ton objet (ex : fenêtre de log)
    • Le serveur
    • Ton message a transmettre


    L'utilisation d'un unique ID (ce que l'on avait adopté pour la première version de ce serveur ) pour un évènement requête/réponse OU une fenêtre est pour moi une bonne idée, on encapsule ainsi le message avec une signature.

    Maintenant reste a savoir ce que signifie cet ID et comment il est crée :
    1. Soit cet ID est "statique" et est associé a une fenêtre, dans ce cas la il faut espérer que les réponses de serveur arrivent dans le même ordre que l'envoi de les requêtes de l'objet, ou être capable de reconnaître une réponse à partir du contenu du message. L'avantage est qu'il sera plus simple pour identifier l'objet destinataire du messages.
    2. Soit cet ID est crée dynamiquement et associé à un évènement. Dans ce cas la fenêtre doit "s'enregistrer' auprès de ton application comme étant le destinataire de ce message, pour éviter les envois "broadcast".La fenêtre doit également contenir un enregistrement de cette signature (un pile d'ID par exemple). Mais tu peux aussi joindre le premier point en ajoutant un préfixe "statique" à ton ID pour identifier la fenêtre.


    Maintenant comment tu souhaites faire l'échange entre l'application et ta fenêtre ?
    Qu'est-ce que propose QT à ce sujet ? Je ne sais pas trop donc mes réponses sont plus ou moins adaptées, les experts ici pourront commenter.
    Je ne pense pas que QT possède le mécanisme des messages des MFC (mais est-ce dur a écrire a partir de l'existant).

    Ajout direct dans l'élément d'une pile appartenant à ta fenêtre : ton application possède une liste ID/Objet et lors de la réception d'un message elle parcours cette liste et empile directement le message avec son ID dans la pile de ta fenêtre. Cela veut dire que celle-ci doit la poller (pas scruter) dans un thread séparé. note : Si le mécanisme MFC-like de message existe la question ne se pose pas car tu utiliseras de l'existant.

    Utilisation de signal/slot : comme on ne souhaite probablement pas créer un signal/objet on aura un signal pour toutes les fenêtres, qui devront ignorer le contenu du message s'il ne lui est pas adressé (un petit switch dessus). Inconvénient : le système de broadcast peut peut-être nuire au perf (quoique un petit switch ..), mais cela peut être un avantage si on souhaite envoyer la même info a plusieurs fenêtres.

    Voilà a peu près les idées qui me viennent...

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