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

Anciens défis Discussion :

[Amnell] Présentation de ma participation [Défi n°2]


Sujet :

Anciens défis

  1. #21
    Rédacteur

    Avatar de johnlamericain
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    3 742
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 3 742
    Points : 8 140
    Points
    8 140
    Par défaut
    Participation de Amnell :

    Plante sous Windows 7, 4.7.4, MSVC2008
    Plante sous Windiows Vista, 4.7.2, MSVC2008

    J'ai pas réçu à passer l'écran de login... Il doit y avoir un truc de ouf derrière pour que ce soit si dur.

  2. #22
    Responsable Qt & Livres


    Avatar de dourouc05
    Homme Profil pro
    Ingénieur de recherche
    Inscrit en
    Août 2008
    Messages
    26 684
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur de recherche
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2008
    Messages : 26 684
    Points : 188 860
    Points
    188 860
    Par défaut
    En effet, le client a tendance à planter quand on l'exécute en dehors de Qt Creator (SDK 1.1.3, installé fraîchement aujourd'hui, Win7 64 bits, MinGW 4.4 32 bits). Par contre, en l'exécutant dans Qt Creator, ça passe sans souci.

  3. #23
    Rédacteur

    Avatar de johnlamericain
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    3 742
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 3 742
    Points : 8 140
    Points
    8 140
    Par défaut
    Citation Envoyé par dourouc05 Voir le message
    En effet, le client a tendance à planter quand on l'exécute en dehors de Qt Creator (SDK 1.1.3, installé fraîchement aujourd'hui, Win7 64 bits, MinGW 4.4 32 bits). Par contre, en l'exécutant dans Qt Creator, ça passe sans souci.
    j'exécute toujours dans Qt Creator, ça marche pas chez moi...

  4. #24
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 617
    Points
    15 617
    Par défaut
    Pareil, ça fonctionne chez moi sous QtCreator (mingw). J'ai testé avec plusieurs version de Qt sans problème (4.7.3, 4.7.4, 4.8). Pour Qt 5, c'est pas très grave, c'était juste pour m'amuser. A priori, ils ont viré la fonction qRound() donc le code compile pas

  5. #25
    Rédacteur

    Avatar de johnlamericain
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    3 742
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 3 742
    Points : 8 140
    Points
    8 140
    Par défaut
    Alors ça doit être MSVC qui fait foirer le truc. C'est pas comme si c'était le compilateur le plus utilisé

  6. #26
    Rédacteur
    Avatar de Amnell
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2009
    Messages
    1 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 840
    Points : 5 545
    Points
    5 545
    Par défaut
    Citation Envoyé par johnlamericain Voir le message
    J'ai pas réçu à passer l'écran de login... Il doit y avoir un truc de ouf derrière pour que ce soit si dur.
    Le crash doit effectivement provenir de MSVC, vu que sous toutes les plateformes que j'ai testées en compilant soit avec GCC, soit avec MinGW, ça passe sans problème. Concernant le "truc de ouf", c'est tout simplement un ping qui calcule la latence de la connexion serveur/client (comme le montre la console du serveur).

    Je suis tout de même soulagé que le problème provienne "juste" du compilateur, vu que je ne voyais pas du tout ce qui aurait pu le provoquer... Sans doute une différence de norme, je ne connais pas bien les différences entre MSVC et les deux autres énoncés plus haut.

  7. #27
    Rédacteur
    Avatar de Amnell
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2009
    Messages
    1 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 840
    Points : 5 545
    Points
    5 545
    Par défaut
    Citation Envoyé par dourouc05 Voir le message
    En effet, le client a tendance à planter quand on l'exécute en dehors de Qt Creator (SDK 1.1.3, installé fraîchement aujourd'hui, Win7 64 bits, MinGW 4.4 32 bits). Par contre, en l'exécutant dans Qt Creator, ça passe sans souci.
    Par planter, tu entends afficher une fenêtre toute blanche ? Si c'est le cas, c'est tout simplement parce qu'il faut que le dossier qml se situe à côté de l'exécutable (Qt Creator le place par défaut dans le répertoire précédent, si je ne me trompe pas) pour que les fichiers QML puissent être interprétés (et surtout : trouvés).

  8. #28
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 617
    Points
    15 617
    Par défaut
    Compilation ok avec msvc 2008-2010 (Qt 4.7.4 et 4.8.0) du client et serveur. Démarrage ok du client et serveur. Par contre, plantage du serveur lorsque je clique sur le bouton "connexion"... étrange

    Pour rappel, ces remarques sont purement informatives et n'entre pas en ligne de compte pour la notation puisque ce n'est pas la version que tu as testé (je crois... )

    EDIT : l'erreur provient d'un seg fault lors d'un changement d'états interne à QtNetwork J'ai pas le détail des informations de déboguage (je ne sais pas utiliser le débogueur de msvc dans Qt Creator) donc je sais pas si c'est un problème dans le code ou dans les libs

  9. #29
    Rédacteur

    Avatar de johnlamericain
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    3 742
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 3 742
    Points : 8 140
    Points
    8 140
    Par défaut
    Citation Envoyé par gbdivers Voir le message
    Compilation ok avec msvc 2008-2010 (Qt 4.7.4 et 4.8.0) du client et serveur. Démarrage ok du client et serveur. Par contre, plantage du serveur lorsque je clique sur le bouton "connexion"... étrange

    Pour rappel, ces remarques sont purement informatives et n'entre pas en ligne de compte pour la notation puisque ce n'est pas la version que tu as testé (je crois... )

    EDIT : l'erreur provient d'un seg fault lors d'un changement d'états interne à QtNetwork J'ai pas le détail des informations de déboguage (je ne sais pas utiliser le débogueur de msvc dans Qt Creator) donc je sais pas si c'est un problème dans le code ou dans les libs
    C'est exactement le même problème que j'ai !

    Fix it

  10. #30
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    Citation Envoyé par Amnell Voir le message
    Je suis tout de même soulagé que le problème provienne "juste" du compilateur, vu que je ne voyais pas du tout ce qui aurait pu le provoquer... Sans doute une différence de norme, je ne connais pas bien les différences entre MSVC et les deux autres énoncés plus haut.
    Malheureusement, ce n'est certainement pas un problème du compilateur :/
    Et a vue de nez c'est une variable non initialisé ou un dépassement de tableau. C’est la joie de l'informatique. Ce n'est pas parce qu’une application marche qu'elle n'est pas buggé. Ca m'est arrivé assez souvent d'avoir un code qui marche jusqu'au jour où j'ajoute un innocent printf Et au finale c'est un bugs qui existait depuis très longtemps.

    Quand les sources seront disponible je regarderais.

  11. #31
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 617
    Points
    15 617
    Par défaut
    J'ai installé le débogueur de msvc pour tester. Il y a bien un pointeur null sous msvc alors qu'il n'y a pas de "problème" sous mingw (dans le sens où le pointeur est pas null... parce que du coup, il y a un problème de validation des pointeurs avant utilisation )

  12. #32
    Rédacteur
    Avatar de Amnell
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2009
    Messages
    1 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 840
    Points : 5 545
    Points
    5 545
    Par défaut
    Si cela peut vous aider dans vos recherches, ce sont les échanges de données par socket qui posent problème après compilation avec MSVC, logiquement (vu que ça crashe lors d'un ping/paquet de login). Côté serveur, la réception des paquets de chaque client se fait dans le fichier customer.cpp suite aux signaux readyRead(). Une fois que le paquet complet est récupéré, il est transmis dans vers la classe présente dans tcpserver.cpp (fonction handleMessage()) qui va appeler la fonction associée au type de paquet (voir opcode.cpp)).

    @yan > Bon courage si tu trouves. Pour ma part, je ne pense pas avoir fait d'erreur de ce type.

  13. #33
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 617
    Points
    15 617
    Par défaut
    C'est la fonction Handler de la classe handle dans la fonction handleMessage qui est invalide. Je n'ai pas encore regardé le pourquoi. J'ai juste ajouté le code suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    if (handle.handler)
       qDebug() << "Handler ok";
    else
       qDebug() << "Handler pas ok";

  14. #34
    Rédacteur
    Avatar de Amnell
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2009
    Messages
    1 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 840
    Points : 5 545
    Points
    5 545
    Par défaut
    Ce sont de simples pointeurs sur fonction présent dans le tableau des opcodes.

  15. #35
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    as tu essayer valgrind sous linux?

  16. #36
    Rédacteur

    Avatar de johnlamericain
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    3 742
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 3 742
    Points : 8 140
    Points
    8 140
    Par défaut
    Oui ça crashe dans la fonction HandleMessage :

    OpcodeHandler &handle = opcodes[opcode];
    (this->*handle.handler)(data, customer);

    qDebug() << QString("Receive opcode %1 from %2 (%3).")
    .arg(handle.name, customer->getName(), customer->getPeerAddress())
    .toAscii().constData();
    La fonction * handler est null et donc fait planter le tout.

  17. #37
    Rédacteur
    Avatar de Amnell
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2009
    Messages
    1 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 840
    Points : 5 545
    Points
    5 545
    Par défaut
    Citation Envoyé par johnlamericain Voir le message
    La fonction * handler est null et donc fait planter le tout.
    Ce n'est pas concevable par rapport au tableau des opcodes ainsi que par rapport aux tests effectués avant ce code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    OpcodeHandler opcodes[MSG_MAX_OPCODES] =
    {
        { "MSG_PING", &TcpServer::handlePing },
        { "MSG_PONG", &TcpServer::unhandled },
        // ...
    };
    Avec OpcodeHandler de la forme :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    struct OpcodeHandler
    {
        /*! Le nom de l'opcode. */
        QString name;
        /*! Le pointeur de fonction associé à l'opcode. */
        void (TcpServer::*handler)(QDataStream*, Customer*);
    };
    Dans aucun cas on a un NULL passé ici, on a toujours une fonction, et &TcpServer::unhandled dans le cas où aucun traitement serait fait suite à la réception du message. On a quoi qu'il arrive un test avant l'appel du handler :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    if (opcode >= MSG_MAX_OPCODES) {
        qDebug() << QString("Receive unexpected opcode %1 from %2. Skipped.")
            .arg(opcode).arg(customer->getPeerAddress()).toAscii().constData();
        return;
    }
    Ce qui garantit que l'on va bien accéder à un élément valide du tableau. Après, il faut garder en tête que cela fonctionne à merveille sous GCC et MinGW donc comment expliquer ce problème ? Il n'aimerait pas la définition de chaque membre de opcodes (cf opcodes.cpp) ?

  18. #38
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    Echange par MP car Defis non terminé :
    Citation Envoyé par Amnell
    Citation Envoyé par yan

    Dans opcodes.h (t'as le même problème dans le client) tu fait

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    #include <QString>
    class TcpServer;
    seulement tu définie
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    struct OpcodeHandler
    {
        /*! Le nom de l'opcode. */
        QString name;
        /*! Le pointeur de fonction associé à l'opcode. */
        void (TcpServer::*handler)(QDataStream*, Customer*);
    };
    alors que le compilateur ne sait pas ce qu'est TcpServer et donc void (TcpServer::*handler)(QDataStream*, Customer*);

    Du coup la taille de ta structure dans opcode.cpp vaut 24 alors que dans TcpServer.cpp elle vaut 8.
    => plantage.

    remplace
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    #include <QString>
    class TcpServer;
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    #include <QString>
    #include "TcpServer.h"
    ou swap les deux include dans opcode.cpp

    et ça marche du tonner. D’ailleurs . Mais je ne vais pas spoiler

    Pour explication plus poussé, je te conseil de demander sur le forum C++. J'aurais du mal à être claire.

    Lorsque l'on utilise la pre déclaration, y as des choses à ne pas faire. Ce qui m'étonne c’est qu'il n'y as pas un warning.
    Salut,

    Merci pour ces explications, j'avoue que je n'aurais pas trouvé. Par contre, je ne comprends pas deux choses :

    1°) Comment ce fait-il que MSVC ne signale pas une erreur dans le cas présent vu qu'au final, il utilise les membres d'une classe indéfinie ?

    2°) C'est en rapport avec cette phrase :

    Du coup la taille de ta structure dans opcode.cpp vaut 24 alors que dans TcpServer.cpp elle vaut 8.
    Je n'ai pas tellement compris ce que tu entendais par là.

    Merci bien de t'être penché sur le problème
    Louis.

    Éclaircissement sur le Problème sous MSVC :

    http://www.developpez.net/forums/d11...e/#post6241045

  19. #39
    Rédacteur
    Avatar de Amnell
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2009
    Messages
    1 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 840
    Points : 5 545
    Points
    5 545
    Par défaut
    Salut,

    Vu que le défi est terminé, je vais enfin pouvoir dévoiler un peu mon application qui a semble-t-il pas mal intrigué du fait de crashs inexpliqués (non, ce n'est pas la belle partie de l'application vu qu'en plus, l'appli avait été testée sur bien des plateformes mais malheureusement pas sous plusieurs compilos - qui eut cru que cette config suffirait à faire sauter une appli... enfin, je n'y croyais pas avant).

    Le serveur

    Le serveur est une application console qui ne fait que récupérer les paquets envoyés par les clients et agir en conséquence. Il ne fait rien de plus, dans le sens où il n'envoie jamais de son propre chef des paquets aux clients : il y a toujours une action d'un client qui le mène à faire cela.

    Les paquets reçus sont identifiés par un système d'opcodes. Ainsi, toutes les réceptions de paquets sont loggués dans la console et sauvegardées dans un fichier de log. Un exemple de logs suite à quelques actions de l'utilisateur sur un client :

    2011-09-16 23:01:02: Initializing server...
    2011-09-16 23:01:02: Server successfully initialized.
    2011-09-16 23:01:02: Initializing database...
    2011-09-16 23:01:02: Database successfully initialized.
    2011-09-16 23:01:02: Initializing simulator...
    2011-09-16 23:01:02: Simulator successfully initialized.
    2011-09-16 23:05:53: New connection from 127.0.0.1.
    2011-09-16 23:05:59: Receive opcode MSG_LOGIN from Jean Dupont (127.0.0.1).
    2011-09-16 23:06:02: Receive opcode MSG_QUERY_PATIENTS_MODEL from Jean Dupont (127.0.0.1).
    2011-09-16 23:06:03: Receive opcode MSG_QUERY_MEDICINE_MODEL from Jean Dupont (127.0.0.1).
    2011-09-16 23:06:03: Receive opcode MSG_QUERY_BODY_PARTS from Jean Dupont (127.0.0.1).
    2011-09-16 23:06:03: Receive opcode MSG_QUERY_PATIENT from Jean Dupont (127.0.0.1).
    2011-09-16 23:06:03: Receive opcode MSG_PING from Jean Dupont (127.0.0.1).
    2011-09-16 23:06:10: Receive opcode MSG_ENTER_CHAT from Jean Dupont (127.0.0.1).
    2011-09-16 23:06:10: Receive opcode MSG_QUERY_CHAT_USERS from Jean Dupont (127.0.0.1).
    2011-09-16 23:06:13: Receive opcode MSG_PING from Jean Dupont (127.0.0.1).
    2011-09-16 23:06:16: Receive opcode MSG_SEND_CHAT_MESSAGE from Jean Dupont (127.0.0.1).
    2011-09-16 23:06:19: Receive opcode MSG_SEND_CHAT_MESSAGE from Jean Dupont (127.0.0.1).
    2011-09-16 23:06:21: Receive opcode MSG_SEND_CHAT_MESSAGE from Jean Dupont (127.0.0.1).
    2011-09-16 23:06:22: Receive opcode MSG_LEAVE_CHAT from Jean Dupont (127.0.0.1).
    2011-09-16 23:06:23: Receive opcode MSG_PING from Jean Dupont (127.0.0.1).
    2011-09-16 23:06:27: Receive opcode MSG_QUERY_ANALYSIS_MODEL from Jean Dupont (127.0.0.1).
    2011-09-16 23:06:33: Receive opcode MSG_PING from Jean Dupont (127.0.0.1).
    2011-09-16 23:06:43: Receive opcode MSG_PING from Jean Dupont (127.0.0.1).
    2011-09-16 23:06:43: Receive opcode MSG_QUERY_PATIENT from Jean Dupont (127.0.0.1).
    2011-09-16 23:06:44: Receive opcode MSG_QUERY_PATIENT from Jean Dupont (127.0.0.1).
    2011-09-16 23:06:50: Receive opcode MSG_MODIFY_PATIENT from Jean Dupont (127.0.0.1).
    2011-09-16 23:06:50: Receive opcode MSG_QUERY_PATIENTS_MODEL from Jean Dupont (127.0.0.1).
    2011-09-16 23:06:50: Receive opcode MSG_QUERY_MEDICINE_MODEL from Jean Dupont (127.0.0.1).
    2011-09-16 23:06:50: Receive opcode MSG_QUERY_BODY_PARTS from Jean Dupont (127.0.0.1).
    2011-09-16 23:06:50: Receive opcode MSG_QUERY_PATIENT from Jean Dupont (127.0.0.1).
    2011-09-16 23:06:53: Receive opcode MSG_PING from Jean Dupont (127.0.0.1).
    2011-09-16 23:07:03: Receive opcode MSG_MODIFY_PRESCRIPTION from Jean Dupont (127.0.0.1).
    2011-09-16 23:07:03: Receive opcode MSG_QUERY_PATIENT from Jean Dupont (127.0.0.1).
    2011-09-16 23:07:03: Receive opcode MSG_PING from Jean Dupont (127.0.0.1).
    2011-09-16 23:07:11: Receive opcode MSG_START_ECG from Jean Dupont (127.0.0.1).
    2011-09-16 23:07:13: Receive opcode MSG_PING from Jean Dupont (127.0.0.1).
    2011-09-16 23:07:13: Receive opcode MSG_STOP_ECG from Jean Dupont (127.0.0.1).
    2011-09-16 23:07:15: Customer Jean Dupont (127.0.0.1) has been disconnected.
    Chaque "MSG_[quelque chose]" correspond à un paquet. Le type est déterminé selon l'opcode spécifié en tête de paquet.

    Le serveur s'appuie sur deux systèmes-piliers : le simulateur (qui simule les données en provenance des divers appareil médicaux) et la base de données.

    La base de données n'est pas une simple QSqlDatabase qui fait du SELECT/UPDATE/INSERT sur la db SQLite. Non, elle ne fait pas cela car selon moi, ce n'est pas optimisé et les clients risqueraient d'attendre une réponse, limitant la fluidité de l'application cliente. Au lancement de l'application, je récupère le contenu de chaque table de ma base de donnée et j'indexe chaque élément dans une classe template nommée DBStore<T>, une liste contenant des entrées de la table concernées. Par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    DBStore<AccountEntry> AccountStore;
    Avec AccountStore qui contient toutes les entrées de la table "account" de la base de données. AccountEntry est une structure de ce type :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    struct AccountEntry : public BaseEntry<AccountEntry>
    {
        int id;
        QString name;
        QString password;
        int level;
     
        // ...
    };
    L'intérêt d'indexer les tables de la base de données dans ce type de chose permet de n'avoir plus aucun SELECT à faire. Lors d'une requête de la part d'un client de la couleur des chaussettes de Jean-Claude, l'infirmier, le serveur tape directement dans le DBStore<ChaussetteEntry> pour retourner la couleur, il n'y a pas de SELECT, donc au final un gain de temps.

    Le client

    Le client a été codé de telle manière que ce soit la partie QML qui détermine quelle action effectuer quand. Le C++ du client n'est là que pour être exploité par la partie QML. Vous connaissez tous le concept de la séparation graphique et logique d'une application Qt avec la partie logique en C++ et la partie QML pour l'interface graphique, avec entre les deux un objet contextuel qui joue le rôle de pont pour permettre la communication. Ici, je considère la partie C++ comme étant un pont entre le QML et le serveur lui-même vu que le C++ n'a aucun rôle décisionnel dans l'application : son rôle se limite à l'envoi de paquet et à la réception de paquets (le système d'identification du paquet se fait également par opcode de manière identique à ce qui a été fait dans le serveur, donc je ne re-détaille pas).

    Côté C++, lors de la phase de conception, j'ai décidé de faire un système de paquets généralisés, dans le sens où le TcpSocket joue le rôle du receveur/envoyeur de paquets, sans plus. Ce n'est pas lui qui transfère les données à l'ancre (l'objet contextuel entre le C++ et le QML), il ne fait aucun traitement. Il possède donc deux types de fonctions : des fonctions d'envoi de paquets et des fonctions de réception. Dans les fonctions de réception, il passe au gestionnaire de hooks les données reçue et son travail s'arrête là.

    On en vient donc au gestionnaire de hooks : qu'est-ce ? C'est un gestionnaire qui contient plusieurs listes de hooks, des classes totalement indépendantes qui s'ajoutent et se retirent sans une ligne de code à changer. Je suppose que vous êtes en train de vous gratter la tête en vous disant : "Qu'est-ce qui me chante ?". J'explicite. Imaginons que nous avons reçu un paquet contenant le nom du patient N. Le serveur va envoyer directement l'info sans l'analyser au gestionnaire de hooks qui va appeler la fonction onReceivePatientName() de tous les hooks branchés sur lui :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void HookMgr::onReceivePatientName(const QString &data)
    {
        foreach (ModuleHook *hook, _moduleHooks)
            hook->onReceivePatientName(data);
    }
    Un hook se créant de la façon suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class PatientFollowUpHook : public ModuleHook
    {
    public:
        PatientFollowUpHook() : ModuleHook() { }
    };
    Et dans la fonction addModuleHooks(), on ajoute juste :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    new PatientFollowUpHook();
    Et c'est tout ! ModuleHook() ajoute comme un grand le hook à la liste des hooks de type ModuleHook du gestionnaire de hooks. En gros, on peut ajouter/retirer des classes quand on le souhaite sans avoir à retoucher quoi que ce soit. Au final, on crée autant de traitements qu'on le souhaite suite à la réception de paquets sans avoir à changer quoi que ce soit en interne.

    Je regrette juste de ne pas l'avoir exploité jusqu'au bout dans le sens où j'ai donné aux hooks des comportements très limités vu que je suis parti sur une utilisation maximale de QML.

    Trêve de paroles, on veut des images !

    L'application se veut être utilisée sur des petites plateformes. C'était d'ailleurs une grosse difficulté vu que faire rentrer beaucoup de données dans un petit espace n'était pas évident.

    Ce qui me désole est que l'application se veut être très esthétique : il y a beaucoup d'animations, une gestion qui me semble intéressante du tactile/souris au niveau de la manipulation des éléments de la fenêtre. Bref, j'aurais voulu vous donner des vidéos plutôt que des screens, mais je n'ai pas le matériel pour.

    Ainsi, voici quelques images :


    La vision du dossier d'un patient avec les prescriptions médicales.


    Les informations du patient (oui, on soigne des patients morts chez nous !)


    L'ECG en temps réel. Notez que le simulateur du serveur s'amuse avec un peu d'aléatoire à modifier légèrement la position des points pour avoir des courbes un tout petit peu "vivantes".


    Mon super color picker QML/JS pour modifier la couleur de l'ECG.


    Les radios (une grande image recomposée à partir des images données dans le dossier radios) avec zoom sur quatre niveaux et possibilité de se balader dessus comme sur Google Map, mais en plus fluide

    J'aurais bien ajouté d'autres choses, comme la vue animée sur 360° du scanner avec possibilité de faire ralentir/accélérer l'animation, mais je suis arrivé au cota de 5 images. Quoi qu'il en soit, mon application ne peut pas se résumer à des screens, vu qu'il y a toute la partie animation derrière.

    Bref, tout ça pour dire que je suis plutôt content de ma participation !

    Bonne soirée,
    Amnell.
    Images attachées Images attachées      

  20. #40
    Membre habitué Avatar de 0x4e84
    Homme Profil pro
    Inscrit en
    Septembre 2002
    Messages
    116
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : Suisse

    Informations forums :
    Inscription : Septembre 2002
    Messages : 116
    Points : 155
    Points
    155
    Par défaut
    Joli !!


+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 3 PremièrePremière 123 DernièreDernière

Discussions similaires

  1. [Défi n°2] [Les geekologues] Présentation de notre participation
    Par Invité dans le forum Anciens défis
    Réponses: 10
    Dernier message: 15/09/2011, 01h00
  2. [Défi n°2] [feda12] Présentation de ma participation
    Par feda12 dans le forum Anciens défis
    Réponses: 20
    Dernier message: 07/06/2011, 20h38
  3. [Défi n°1] [Amnell] Présentation de ma participation
    Par Amnell dans le forum Anciens défis
    Réponses: 59
    Dernier message: 06/03/2010, 16h15
  4. [Défi n°1] [0x4e84] - Présentation de ma participation
    Par 0x4e84 dans le forum Anciens défis
    Réponses: 11
    Dernier message: 01/03/2010, 10h44
  5. [Défi n°1] [Shooter74] Présentation de ma participation
    Par Shooter74 dans le forum Anciens défis
    Réponses: 6
    Dernier message: 28/01/2010, 21h54

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