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

C++ Discussion :

Meilleur facon de recevoir/traiter des paquets


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juin 2012
    Messages
    41
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Services à domicile

    Informations forums :
    Inscription : Juin 2012
    Messages : 41
    Par défaut Meilleur facon de recevoir/traiter des paquets
    Bonjour,

    Je fais appel a vous tous pour m'aider a trouver une façon clair et rapide pour établir une connexion, recevoir des paquet et réagir en conséquence.

    Le fait est que plusieurs paquets peuvent êtres envoyés d'un coup, et qu'il n'y a pas moyen de savoir combien de paquets vont arriver exactement.


    En ce qui me concerne j'ai essayé 2 méthodes, chacune est parvenue a une échec :

    La première était de créer une boucle qui recevrait les paquet et les traiterait directement.

    Comme rien ne vaut un exemple simple :

    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
     
    While(connected)
    {
        // réception des données avec recv()
        // Vérification du paquet 
        switch(type de paquet)
        {
              case paquet1 :
                    // On réagit en conséquence
                    // On envoie éventuellement une réponse, si réponse 
                    // est attendue
                    break;
              case paquet2 :
                    // On réagit en conséquence
                    break;
              default :
                    // On réagit en conséquence
                    break;
        }
    }
    Mais cette méthode ne réceptionnait pas tous les paquets, les paquets prenait trop de temps à être traités et donc il y avait certains messages non réceptionnés. Ceci menant à une erreur.

    J'ai donc opté pour une boucle d'écoute (threadée) qui stockerait les paquet dans une variable de type "queue" . A coté de cela j'ai créée une fonction processQueue(), qui se chargerait de vider la queue et traiter les paquets.
    Mais hélas cette fonction aussi était vouée a l'échec. Il y avait souvent acces concurrents a mes variables membres, et les mutex ajoutés pour régler cela ne faisait que ralentir le code, voir le stopper.

    un petit exemple :

    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
     
    listener()
    {
        while(true)
        {
            // Reception des données
            // stockage des données dans une variables queue
        }
    }
    processQueue()
    {
        // Boucle vidant la queue et faisant appel la fonction adéquate en fonction
        // du message
    }
     
    // Et dans le constructeur on gère thread

    Petit moment de répit, vous suivez toujours ??



    Voila ce qui en est de mon coté, je vous pose donc la question a vous : comment feriez vous pour récupérer les paquets ?



    PS : Ceci peut également être vu comme un sondage, je pense d'ailleurs mettre une balise [sondage] dans le titre ?

  2. #2
    Membre Expert
    Avatar de imperio
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2010
    Messages
    872
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2010
    Messages : 872
    Par défaut
    Je presume que tu utilises le protocole UDP donc. Si tu n'as pas besoin de vitesse, sache que le protocole TCP permet la reception de tous les paquets dans l'ordre dans lequel ils ont ete envoyes.

    Bref, sinon pour repondre a ta question, si tu utilises effectivement le protocole UDP cela signifie qu'il n'est pas important de recevoir tous les paquets. Par consequent je mettrais le numero du paquet dans les 4 premiers octets puis les infos derriere. Ainsi, si le numero du paquet recu est plus faible que le dernier numero recu, cela signifie qu'il est inutile de traiter l'information qu'il contient.

  3. #3
    Membre averti
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juin 2012
    Messages
    41
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Services à domicile

    Informations forums :
    Inscription : Juin 2012
    Messages : 41
    Par défaut
    Bonjour,

    Non j'utilise bien le protocole TCP. Mais il se trouve qu'il ne reçois pas tous les paquets . Quand je lance deux recv() de suite, je reçois les deux. Mais quand j'essaie de traiter un paquet entre, je rate systématiquement le paquet d'après, ce qui mène a une erreur 10054 .

    Je suis totalement bloqué depuis 3 jours et je ne comprends pas pourquoi .

    Mon hypothèse était donc que le serveur lançait un send() avant que mon recv() ne soit prêt .

    Voila donc pourquoi j'ai créée ce topic. Comment faites vous, en général pour recevoir une suite de paquet ? (je ne demande pas de code concret mais juste une structure basique si possible, car je ne sais plus quoi faire )

  4. #4
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut
    Bonjour,

    Pourrais-tu nous montrer ton code ?

    Est-ce que tu ne fermerais pas ta connexion pendant que tu traites ton paquet

  5. #5
    Membre averti
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juin 2012
    Messages
    41
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Services à domicile

    Informations forums :
    Inscription : Juin 2012
    Messages : 41
    Par défaut
    Non la connexion est bien ouverte, le recv() ne fais que attendre un message sans renvoyer d'erreur. D'ailleurs parfois il arrive que le code sois assez rapide et la je reçois le deuxième paquet .

    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
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
     
     
    #include "network/server.h"
     
    // ################################################
    // ##
    // ##   Configuration de la socket
    // ##   Connexion
    // ##   Destruction
    // ##
    // ################################################
     
    server::server()
    {
        framework = new handler();
        framework->setLogins(usr, pass);
            #if defined (WIN32)
                    erreur = WSAStartup(MAKEWORD(2,2), &WSAData);
            #else
                    erreur = 0;
            #endif
     
        if(!erreur)
        {
            // create socket
            sock = socket(AF_INET, SOCK_STREAM, 0);
     
            // Connection configuration
            sin.sin_addr.s_addr = inet_addr(ip);
            sin.sin_family = AF_INET;
            sin.sin_port = htons(port);
            // If connection
            if(connect(sock, (SOCKADDR*)&sin, sizeof(sin)) != SOCKET_ERROR)
            {
                thread = new pthread_t();
                pthread_create(thread, NULL, StaticThreadFunc, this);
                pthread_join(*thread, NULL);
                starter_check = true;
            }
            else
                starter_check = false;
     
        }
        else
            starter_check = false;
    }
     
     
    server::~server()
    {
            closesocket(sock);
     
            #if defined (WIN32)
                    WSACleanup();
            #endif
     
    }
     
    // ################################################
    // ##
    // ##   Creation de la boucle d'écoute
    // ##   
    // ##
    // ##
    // ################################################
     
    void *server::StaticThreadFunc(void *Param)
    {
        server* Obj = reinterpret_cast<server*>(Param);
        return Obj->listener();
    }
    void* server::listener()
    {
        int ok;
        while(true)
        {
            // Reception des données
            ok = recv(sock, buffer, sizeof(buffer), 0);
            // Vérifier si reception de données
            if(ok == SOCKET_ERROR)
            {
                cout << "error" << endl;
                system("pause");
            }
            processMessage();
        }
    }
    void server::processMessage()
    {
        // Recupération de l'id du paquet
        Id = getId(buffer);
        // Recupération du message & lancement de l'évenement
        framework->process(Id, sock, buffer);
        // La réponse est envoyée dans cette derniere fonction
    }

  6. #6
    Membre Expert
    Avatar de imperio
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2010
    Messages
    872
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2010
    Messages : 872
    Par défaut
    Pas tip top ta boucle infinie... Je ferais plutot ca a ta place :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    while((ok = recv(sock, buffer, sizeof(buffer), 0)) > 0)
    {
        processMessage();
    }
    // Vérifier si reception de données
    if(ok == SOCKET_ERROR)
    {
        cout << "error" << endl;
        system("pause");
    }
    Sinon pour ton erreur je vois pas trop d'ou elle pourrait venir a part une deconnexion du serveur...

Discussions similaires

  1. Réponses: 3
    Dernier message: 27/06/2011, 10h28
  2. [MySQL] Meilleure facon d'insérer des données dont certaines peuvent être en double ?
    Par beninsky dans le forum PHP & Base de données
    Réponses: 5
    Dernier message: 15/05/2010, 09h17
  3. [MySQL] Meilleure facon de récupérer des resultats sur une période
    Par beninsky dans le forum PHP & Base de données
    Réponses: 1
    Dernier message: 29/03/2010, 15h01
  4. le meilleur langage pour traiter des gros fichiers xml
    Par hansaplast dans le forum XML/XSL et SOAP
    Réponses: 7
    Dernier message: 06/07/2009, 22h35
  5. meilleure facon de gerer des interruptions ?
    Par kamouminator dans le forum Linux
    Réponses: 0
    Dernier message: 20/04/2009, 11h39

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