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

Réseau C Discussion :

Fonctionement fonction recv()


Sujet :

Réseau C

  1. #1
    Membre éclairé
    Inscrit en
    Février 2008
    Messages
    302
    Détails du profil
    Informations forums :
    Inscription : Février 2008
    Messages : 302
    Par défaut Fonctionement fonction recv()
    Bonsoir ...

    Je me pose des questions sur la fonction recv() ...

    Alors voila, je vous explique !

    Du cote serveur, j'effectue l'envoie d'un message avec un send() ...
    Je ne fais pas de recv() tout de suite ...
    Ou est ce que le message est stocké ?

    Enfin, est ce que vous avez de la doc sur le fonctionnement d'une carte réseau, sur la facon de gerer les paquet qui arrive ?

    merci

  2. #2
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 69
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par nuFox Voir le message
    Je me pose des questions sur la fonction recv() ...

    Du cote serveur, j'effectue l'envoie d'un message avec un send() ...
    Je ne fais pas de recv() tout de suite ...
    Ou est ce que le message est stocké ?
    Dans les buffers des couches systèmes. Quand il n'y a plus de place, les paquets (les plus anciens ?) sont perdus...

    Il font conserver un certain synchronisme...
    Enfin, est ce que vous avez de la doc sur le fonctionnement d'une carte réseau, sur la facon de gerer les paquet qui arrive ?
    La notion de carte réseau est très 'bas niveau'. Les systèmes proposent en général une abstraction appelée socket (tu connais, puisque recv() en fait partie) qui évite les tracas liés à la gestion des cartes réseaux (Ethernet, USB, Wifi... peu importe. Un socket est un socket...)

    Quelle est la vraie question ?

  3. #3
    Membre éclairé
    Inscrit en
    Février 2008
    Messages
    302
    Détails du profil
    Informations forums :
    Inscription : Février 2008
    Messages : 302
    Par défaut
    Merci pour ta premiere réponse ...

    Enfait voila ... j'ai du mal a m'expliquer ...

    Le paquet recu sur un socket ... Est ce que je peux le recup quand je veux avec la fonction recv() ? Ou est ce que je suis obligé de faire un send()/recv() l'un après l'autre ?

    Est ce que les paquets recu s'entassent dans un pile de type FIFO ?

    Il ne s'entasse pas sur un buffer de la carte réseaux ? Mais sur le buffer que l'on a créée vec le socket ?

  4. #4
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 69
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par nuFox Voir le message
    Le paquet recu sur un socket ... Est ce que je peux le recup quand je veux avec la fonction recv() ?
    Ben pas 2 heures après... En fait ça dépend du débit, du système, du protocole...

    En UDP, c'est du "send and forget". Celui qui reçoit doit être prêt, car l'émetteur balance ses paquets à la suite... Il y a des risques de perte ou de congestion. Néanmoins, un protocole 'supérieur' (TFTP, par exemple) peut gérer ça...

    En TCP, chaque paquet est 'acquitté'. Le paquet suivant n'est émis que si le précédent est arrivé à bon port. Est-ce qu ça signifie qu'il a été lu ? Je ne pense pas (à vérifier dans la doc 'SOCKET'). Je pense que ça veut surtout dire qu'il a été reçu par le système et stocké en FIFO. Il y a risque de congestion si on dépasse le nombre de stockage autorisé, qui dépend du système...

    Ou est ce que je suis obligé de faire un send()/recv() l'un après l'autre ?
    Bah, ça dépend un peu de ton application (volume, débit , taille des paquets...). Tu veux faire quoi ?

    Est ce que les paquets recu s'entassent dans un pile de type FIFO ?
    Oui.
    Il ne s'entasse pas sur un buffer de la carte réseaux ? Mais sur le buffer que l'on a créée vec le socket ?
    Non. C'est dans le système. On n'y a pas accès...

    Mais pourquoi toutes ces questions ? Essayes, tu verras bien...

  5. #5
    Membre éclairé
    Inscrit en
    Février 2008
    Messages
    302
    Détails du profil
    Informations forums :
    Inscription : Février 2008
    Messages : 302
    Par défaut
    Enfait je dois réaliser une DLL de communication avec un serveur (donc moi je suis le client), cette DLL aura pour but d'envoyer et recevoir des paquets ...
    (assez petit il ne depasse pas 14Byte de données). C'est dll est cyclique,

    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
     
      // Step = 0 -> Initialisation + connection.
      if(step == 0){
        connection();
      }
     
      // Step = 1 -> Recuperer tout les parametres.
      if(step == 1){
     
        sending(2, cpt, 0);
        receive(cluster1, paramLv);
     
        // Compteur de passage dans initialisation
        cpt++;
     
        // Initialisation terminee
        if(cpt == NBPARAM){
          memcpy((void *)paramOld, (const void*)paramLv, NBPARAM);
          step = 2;
        }
      }
     
      //Step = 2 -> Envoyer et recevoir des données normalement.
      if(step == 2){
     
        //receive(cluster1, paramLv);
     
        // Boucle pour voir si le tableau des parametres a été modifié.
        for(cpt = 0; cpt < NBPARAM; cpt++){
          if(paramLv[cpt] != paramOld[cpt]){
            sending(3, cpt, paramLv[cpt]);
            receive(cluster1, paramLv);
            paramOld[cpt] = paramLv[cpt];
            cpt = NBPARAM;
          }
        }
     
        // Status and Measures reading (TCS request)
        cptReqStat++;
        if(cptReqStat == 10){
          sending(1,0,0);
          receive(cluster1, paramLv);
          cptReqStat = 0;
        }
      }
     
      //Step = 3 -> Deconnection.
      if(step == 3){
        close(); 
      }           
    }
    Pour la réalisation, chaque fois que je fais un send (sur le client vers le serveur), je fais le recv tout de suite ... Parce que dans la configuration du projet, le client envoie un message au serveur et le serveur lui renvoie la réponse ... Donc pour chaque send() effectué j'ai un recv() qui le suit (Pour ne pas que le recv() soit bloquant, j'utilise un select) ... Cette méthode me parrassait bonne (comme indiqué au dessus) ...

    Mais la personne responsable de mon stage, voudrait que je fasse tout mes send() et ne faire qu'un recv() en premier donc :

    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
     
      //Fonction recv() qui va prendre les paquets sur la cible
      receive(cluster1, paramLv);
     
      // Step = 0 -> Initialisation + connection.
      if(step == 0){
        connection();
      }
     
      // Step = 1 -> Recuperer tout les parametres.
      if(step == 1){
     
        sending(2, cpt, 0);
     
        // Compteur de passage dans initialisation
        cpt++;
     
        // Initialisation terminee
        if(cpt == NBPARAM){
          memcpy((void *)paramOld, (const void*)paramLv, NBPARAM);
          step = 2;
        }
      }
     
      //Step = 2 -> Envoyer et recevoir des données normalement.
      if(step == 2){
     
        // Boucle pour voir si le tableau des parametres a été modifié.
        for(cpt = 0; cpt < NBPARAM; cpt++){
          if(paramLv[cpt] != paramOld[cpt]){
            sending(3, cpt, paramLv[cpt]);
            paramOld[cpt] = paramLv[cpt];
            cpt = NBPARAM;
          }
        }
     
        // Status and Measures reading (TCS request)
        cptReqStat++;
        if(cptReqStat == 10){
          sending(1,0,0);
          cptReqStat = 0;
        }
      }
     
      //Step = 3 -> Deconnection.
      if(step == 3){
        close(); 
      }           
    }
    Donc c'est pour ca que je voulais savoir si le socket stockait ces messages quelque part avant que l'on fasse un recv() ... Pour savoir si meme 4paquets sont arrivés, si je vais les recevoir dans l'ordre dans lequel je les ai demandé.

    Et donc si j'ai bien compris, la fonction recv() va aller chercher les paquets sur la pile systeme ... ?

    Merci de ton aide et du temps que tu passes sur mes questions !

  6. #6
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 69
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par nuFox Voir le message
    Enfait je dois réaliser une DLL de communication avec un serveur (donc moi je suis le client), cette DLL aura pour but d'envoyer et recevoir des paquets ...
    Bizarre. En général, on met la partie socket dans l'application. Pourquoi une DLL ? Enfin, je suppose que c'est possible... Et si plusieurs applications utilisent cette DLL, c'est prévu ? On sait qui fait quoi ? Les données sont bien contextuelles ?
    (assez petit il ne depasse pas 14Byte de données). C'est dll est cyclique,
    Je ne comprends pas cette phrase, il y a 2 verbes... Tu veux dire "Cette DLL est cyclique" ? Ca n'a aucun sens. Une DLL n'est pas un processus. Elle n'a pas de vie propre. C'est une bibliothèque qui dépend d'un processus courant (application).

    Tu es sûr que ce n'est pas un 'service' (ou daemon) que tu veux faire ?
    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
     
      // Step = 0 -> Initialisation + connection.
      if(step == 0){
        connection();
      }
     
      // Step = 1 -> Recuperer tout les parametres.
      if(step == 1){
     
        sending(2, cpt, 0);
        receive(cluster1, paramLv);
     
        // Compteur de passage dans initialisation
        cpt++;
     
        // Initialisation terminee
        if(cpt == NBPARAM){
          memcpy((void *)paramOld, (const void*)paramLv, NBPARAM);
          step = 2;
        }
      }
     
      //Step = 2 -> Envoyer et recevoir des données normalement.
      if(step == 2){
     
        //receive(cluster1, paramLv);
     
        // Boucle pour voir si le tableau des parametres a été modifié.
        for(cpt = 0; cpt < NBPARAM; cpt++){
          if(paramLv[cpt] != paramOld[cpt]){
            sending(3, cpt, paramLv[cpt]);
            receive(cluster1, paramLv);
            paramOld[cpt] = paramLv[cpt];
            cpt = NBPARAM;
          }
        }
     
        // Status and Measures reading (TCS request)
        cptReqStat++;
        if(cptReqStat == 10){
          sending(1,0,0);
          receive(cluster1, paramLv);
          cptReqStat = 0;
        }
      }
     
      //Step = 3 -> Deconnection.
      if(step == 3){
        close(); 
      }           
    }
    Euh, c'est le code quoi ça ? Il y a plein de fonctions inconnues... (connection(), sending(), receive()) C'est un automate ? Il est géré par qui ?

    Pour la réalisation, chaque fois que je fais un send (sur le client vers le serveur),
    Tu veux dire "du client vers le serveur ?"
    je fais le recv tout de suite ... Parce que dans la configuration du projet, le client envoie un message au serveur et le serveur lui renvoie la réponse ... Donc pour chaque send() effectué j'ai un recv() qui le suit (Pour ne pas que le recv() soit bloquant, j'utilise un select) ... Cette méthode me parrassait bonne (comme indiqué au dessus) ...
    Ca me parait correct. Le select() est aussi bloquant que le recv(), mais il peut se débloquer sur timeout... Attention, je rappelle que sous Windows, select() ne gère que les sockets.
    Mais la personne responsable de mon stage, voudrait que je fasse tout mes send() et ne faire qu'un recv() en premier donc :
    Comment ça en premier ? ON peut éventuellement faire ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    send()
    send()
    send()
    recv()
    mais pas l'inverse,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    recv()
    send()
    send()
    send()
    ça n'a aucun sens pour un client.

    Le protocle applicatif est forcément du genre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
        Client      Serveur
          |           |
          |  commande |
    send()| --------->|recv()
          |           |
          |  reponse  |
    recv()| <---------|send()
          |           |
    sinon, ça ne tient pas debout...

  7. #7
    Membre éclairé
    Inscrit en
    Février 2008
    Messages
    302
    Détails du profil
    Informations forums :
    Inscription : Février 2008
    Messages : 302
    Par défaut
    Je crée une DLL pour pouvoir l’inserer dans un autre programme (LabView si tu connais) … Donc pour y inclure du C, je suis obligé de faire une DLL. Et donc une seule application utilise cette DLL.
    Oui je veux dire que la DLL est cyclique … J’entends par la que l’on ne fait que passer a travers … une fois toute les opérations faites, on sort de la DLL et on recommence.

    Le code que je vous ai donné correspond justement au cycle !
    Les fonctions inconnue corresponde a des fonctions que j’ai créée, sur ce point elle fonctionne correctement, puisque je sais communiquer avec le serveur (qui est un automate), je sais lui envoyer des messages et recevoir ses réponses …

    Tu veux dire "du client vers le serveur ?"
    Oui c’est ce que je voulais dire …

    recv()
    send()
    send()
    send()
    Comme la DLL est cyclique … Il y a bien un moment ou il ne fera plus la difference entre le debut et la fin … Donc il va faire le dernier send … et comme il va retourner directement dans la dll il va pouvoir faire son recv().


    Donc au final, le premier code mis sur le forum est plus logique que le deuxieme ? Est-ce qu’il y aurait de la documentation sur ce principe ? Histoire d’avoir des element pour prouver que ma méthode est correct.

    Merci d’avance

  8. #8
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 69
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par nuFox Voir le message
    Je crée une DLL pour pouvoir l’inserer dans un autre programme (LabView si tu connais) … Donc pour y inclure du C, je suis obligé de faire une DLL. Et donc une seule application utilise cette DLL.
    OK.
    Oui je veux dire que la DLL est cyclique … J’entends par la que l’on ne fait que passer a travers … une fois toute les opérations faites, on sort de la DLL et on recommence.
    Ah, elle est 'appelée cycliquement' (ses fonctions, en fait...). C'est pas pareil. Elle joue donc son rôle classique de 'fournisseur de fonction'. OK. Je comprends mieux. Il faut être précis sur les termes, sinon, on ne comprend rien...

    Le code que je vous ai donné correspond justement au cycle !
    C'est donc du code applicatif, et les fonctions 'inconnues' sont celles fournies par la DLL, c'est bien ça ? On est pas dans ta tête. Quelques lignes d'explications ne sont pas superflues...
    Les fonctions inconnue corresponde a des fonctions que j’ai créée, sur ce point elle fonctionne correctement, puisque je sais communiquer avec le serveur (qui est un automate), je sais lui envoyer des messages et recevoir ses réponses …
    comme ça, par exemple... OK


    Comme la DLL est cyclique … Il y a bien un moment ou il ne fera plus la difference entre le debut et la fin …
    Euh, une DLL, c'est juste une bibliothèque de fonctions que l'application appelle quand elle veut... C'est quoi 'il' ?
    Donc il va faire le dernier send … et comme il va retourner directement dans la dll il va pouvoir faire son recv().
    Je ne vois pas ce qui peut 'retourner dans la DLL'... Explique...

    Donc au final, le premier code mis sur le forum est plus logique que le deuxieme ?
    A mon sens, oui.
    Est-ce qu’il y aurait de la documentation sur ce principe ? Histoire d’avoir des element pour prouver que ma méthode est correct.
    Bah non, le petit schéma que j'ai fait (architeture client/serveur de base) et le bon sens devraient suffire..

  9. #9
    Membre éclairé
    Inscrit en
    Février 2008
    Messages
    302
    Détails du profil
    Informations forums :
    Inscription : Février 2008
    Messages : 302
    Par défaut
    Tout d'abord, excuse moi sur le faite que je m'exprime mal ... Ca me parrait logique quand je l'écris ... J'en suis désolé.

    Comme la DLL est cyclique … Il y a bien un moment ou il ne fera plus la difference entre le debut et la fin …
    Euh, une DLL, c'est juste une bibliothèque de fonctions que l'application appelle quand elle veut... C'est quoi 'il' ?
    Pour le IL je veux parler du programme qui va utiliser la DLL... Dufaite que le programme va entrer dans la DLL excecuter le code et sortir de la DLL. Pour recommencer une infinité de fois. (d'ou le terme cyclique)

    Donc il va faire le dernier send … et comme il va retourner directement dans la dll il va pouvoir faire son recv().
    Je ne vois pas ce qui peut 'retourner dans la DLL'... Explique...
    Le programme ... Comme je dois en permanence envoyer et recevoir des messages et que la DLL ne peut pas etre blocante (je veux dire par la que l'on ne peut pas rester trop longtemps dans la DLL car sinon le programme ou on a inserer la DLL n'est pas content et il plante, c'est d'ailleur pour ca que j'ai du utiliser un select pour la fonction recv() ), il faut donc que le programme rentre dans la DLL en appelant la fonction à utiliser qui va executer une suite de tache, pi sortir de la fonction après avoir fini les taches pour re rentrer dans la fonction .. Et ainsi de suite.


    Moi aussi ca me parraissait logique .. Pour un send() on fait un recv() ...
    Mais mon bon sens apparement ne prime pas sur le bon sens de mon maitre de stage. Et donc voila ...



    Pour bien clarifier la situation ...

    Je suis le client, j'effectue un envoie de messages avec la fonction send(), le serveur recoit mon message et me renvoie une réponse. Imaginons que sur le client je ne fasse pas de recv() dans l'immédiat ... Le message va etre stocké quelque part? Ce quelque part comme tu la dis avant "Dans les buffers des couches systèmes."
    On ne sait pas acceder a cette zone ?
    Seul la fonction recv() y accede pour recuperer le message ?
    Ce buffer a une taille de combien ?
    Le messages y sont supprimés après un certain temps ? Ou les données sont écraser a chaque ecriture ?

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 401
    Par défaut
    Citation Envoyé par nuFox Voir le message
    Je suis le client, j'effectue un envoie de messages avec la fonction send(), le serveur recoit mon message et me renvoie une réponse. Imaginons que sur le client je ne fasse pas de recv() dans l'immédiat ... Le message va etre stocké quelque part? Ce quelque part comme tu la dis avant "Dans les buffers des couches systèmes."
    On ne sait pas acceder a cette zone ?
    Seul la fonction recv() y accede pour recuperer le message ?
    Ce buffer a une taille de combien ?
    Le messages y sont supprimés après un certain temps ? Ou les données sont écraser a chaque ecriture ?
    1. Seule la fonction recv() y accède.
    2. Si je me souviens bien, c'est réglable par différentes fonctions, mais sous Windows, ça se chiffre généralement en kilo-octets.
    3. Les données ne sont ni supprimées ni écrasées. Si le buffer est plein, les données suivantes sont refusées et c'est l'envoyeur qui bloque jusqu'à ce qu'il y ait de la place dans le buffer.
    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.

  11. #11
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 69
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par nuFox Voir le message
    Tout d'abord, excuse moi sur le faite que je m'exprime mal ... Ca me parrait logique quand je l'écris ...
    Phénomène bien connu, c'est pourquoi j'ai précisé "on n'est pas dans ta tête"... On a pas le contexte, le vécu...

    Pour le IL je veux parler du programme qui va utiliser la DLL... Dufaite que le programme va entrer dans la DLL excecuter le code et sortir de la DLL. Pour recommencer une infinité de fois. (d'ou le terme cyclique)
    OK. En franglais de geek, ça s'appelle "l'application"...

    Ce qui est cyclique, c'est l'appel... OK.

    Le programme ... Comme je dois en permanence envoyer et recevoir des messages et que la DLL ne peut pas etre blocante (je veux dire par la que l'on ne peut pas rester trop longtemps dans la DLL car sinon le programme ou on a inserer la DLL n'est pas content et il plante,
    Inséré ? On a rien inséré du tout. Je rappelle qu'une DLL est une bibliothèque de fonctions. L'application se contente d'appeler ces fonctions.
    c'est d'ailleur pour ca que j'ai du utiliser un select pour la fonction recv() ), il faut donc que le programme rentre dans la DLL en appelant la fonction à utiliser qui va executer une suite de tache, pi sortir de la fonction après avoir fini les taches pour re rentrer dans la fonction .. Et ainsi de suite.
    Qu'est-ce qui peut être bloquant chez un client ? Un recv() qui s'éternise parce que le client ne répond pas. C'est de ça que tu t'es protégé avec le select() ? Tu as mis un timeout court ? Alors dit le, ce sera plus clair. Il faut cesser les devinettes, on perd du temps...
    Moi aussi ca me parraissait logique .. Pour un send() on fait un recv() ...
    Pas forcément. Comme déjà expliqué, on peut faire plusieurs send() avant un recv(). Une solution pour ne pas être gêné par les blocages est d'utiliser les threads. Tu crées un thread de réception, et il se débrouille tout seul. Quand il est bloqué en attente de réception, le reste de l'application se déroule normalement. Plus besoin de select() évidemment...

    http://emmanuel-delahaye.developpez.com/pthreads.htm
    Mais mon bon sens apparement ne prime pas sur le bon sens de mon maitre de stage. Et donc voila ...
    Ce qui ne va pas, c'est de commencer par un recv(). Si on envoie jamais rien au serveur, celui-ci ne fera pas de réponse (à moins qu'il existe un mécanisme d'évènements spontanée, genre 'polling des clients' de la part du serveur, mais c'est rare et couteux...)

    Je suis le client, j'effectue un envoie de messages avec la fonction send(), le serveur recoit mon message et me renvoie une réponse.
    Logique. OK.
    Imaginons que sur le client je ne fasse pas de recv() dans l'immédiat ... Le message va etre stocké quelque part? Ce quelque part comme tu la dis avant "Dans les buffers des couches systèmes."
    Probablement. Quelle importance ?
    On ne sait pas acceder a cette zone ?
    Pas directement. recv() est fait pour ça...
    Seul la fonction recv() y accede pour recuperer le message ?
    Oui.
    Ce buffer a une taille de combien ?
    De combien de quoi ? Taille d'un message ou nombre de buffer ? De toutes façons, ces informations font parties de la configuration du système. C'est important ?
    Le messages y sont supprimés après un certain temps ?
    Probablement pas
    Ou les données sont écraser a chaque ecriture ?
    Il y a une FIFO. Tout est fait pour que ça fonctionne. C'est au protocole supérieur (applicatif) de vérifier si il ya des pertes (checksum etc.)...

    J'ai du mal à comprendre tes craintes. Tu as un débit de paquets ridiculement bas et tu te pose toutes ces questions, alors qu'un Linux de base sur un Pentium de base sait router des milliers de paquets à la seconde...

    Fait déjà une application qui fonctionne, après on verra si il y a des problèmes de performances. Une chose à la fois...

  12. #12
    Membre éclairé
    Inscrit en
    Février 2008
    Messages
    302
    Détails du profil
    Informations forums :
    Inscription : Février 2008
    Messages : 302
    Par défaut
    Mes craintes viennent du faite que mon maitre de stage m'a cassé avec plein de questions qui pour moi me semblait sans importance (les questions correspondes aux différentes questions posées) ... Mais qui apparemment avait de l'importance pour mon maitre de stage. Mais maintenant j'ai les réponses a mes questions ... Et donc ma méthode pour réaliser le projet et bonne, mais ca méthode peut etre aussi implémentée ...


    Qu'est-ce qui peut être bloquant chez un client ? Un recv() qui s'éternise parce que le client ne répond pas. C'est de ça que tu t'es protégé avec le select() ? Tu as mis un timeout court ? Alors dit le, ce sera plus clair. Il faut cesser les devinettes, on perd du temps...
    Le recv() n'est plus bloquant grace au select et un timeout court.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
      timeout.tv_sec = 0;
      timeout.tv_usec = 100000;

    Le programme ... Comme je dois en permanence envoyer et recevoir des messages et que la DLL ne peut pas etre blocante (je veux dire par la que l'on ne peut pas rester trop longtemps dans la DLL car sinon le programme ou on a inserer la DLL n'est pas content et il plante,
    Inséré ? On a rien inséré du tout. Je rappelle qu'une DLL est une bibliothèque de fonctions. L'application se contente d'appeler ces fonctions.
    Inserer dans le sens ou je veux dire l'application ou j'ai placé ma dll pour pouvoir appeler les fonctions de ma DLL.


    Fait déjà un système qui fonctionne, après on verra si il y a des problèmes de performances. Une chose à la fois...
    Mon système est déjà au point et tourne parfaitement (enfin pour ce qu'il fait déjà)... C'est juste que ca ne rentre pas dans le principe de conception de programme de mon maitre de stage ... Et donc je dois modifier mon code, mais avant de le faire je me renseigne pour voir si c'est possible.


    Si ca peut t'aider a y voir plus clair pour ne pas perdre de temps, voici mon code complet :
    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
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    402
    403
    404
    405
    406
    407
    408
    409
    410
    411
    412
    413
    414
    415
    416
    417
    418
    419
    420
    421
    422
    423
    424
    425
    426
    427
    428
    429
    430
    431
    432
    433
    434
    435
    436
    437
    438
    439
    440
    441
    442
    443
    444
    445
    446
    447
    448
    449
    450
    451
    452
    453
    454
    455
    456
    457
    458
    459
    460
    461
    462
    463
    464
    465
    466
    467
    468
    469
    470
    471
    472
    473
    474
    475
    476
    477
    478
    479
    480
    481
    482
    483
    484
    485
    486
    487
    488
    489
    490
    491
    492
    493
    494
    495
    496
    497
    498
    499
    500
    501
     
    // ********************************************************
    // Les includes
    // ********************************************************
    #include <winsock2.h> // Pour les fonctions socket.
    #include <pthread.h>  // Pour les Threads.
    #include <stdio.h>    // Pour les messageBox.
     
    // ********************************************************
    // Defines
    // ********************************************************
    #define NBPARAM 10
    #define MAXSIZEPACKET 14
    #define SIZEBUFFER 20
     
    // ********************************************************
    // Structures
    // ********************************************************
    struct statMeasReq{ 
      char control;
      char lenght;
      unsigned short checksum;
      unsigned short packetID;
    };
     
    struct commParaRead{
      char control;
      char lenght;
      unsigned short checksum;
      unsigned short index;
    };
     
    struct commParaWrit{
      char control;
      char lenght;
      unsigned short checksum;
      unsigned short index;
      unsigned short value;
    };
     
    struct packetRec{
      char control;
      char lenght;
      unsigned short checksum;
      unsigned short id;
      char *data;    
    };
     
    typedef struct{
      char control;
      char lenght;
      unsigned short checksum;
      unsigned short packetID;
      unsigned short stat1;
      unsigned short stat2;
      unsigned short meas1;
      unsigned short meas2;    
    }statMeasRead;
     
    struct commParaReadWrit{
      char control;
      char lenght;
      unsigned short checksum;
      unsigned short index;
      short value;
      unsigned short minVal;
      unsigned short maxVal;
    };
     
    struct packetRejected{
      char control;
      char lenght;
      unsigned short checksum;
      unsigned short index;
    };
     
    // ********************************************************
    // Définition des variables
    // ********************************************************
    WSADATA initialisation_win32;           // Variable permettant de récupérer la structure d'information sur l'initialisation.
     
    //char *ip_adr = "200.0.1.233";         // Adresse IP du serveur.
    //unsigned short port = 2000;           // Port de communication avec le serveur.
     
    char *ip_adr = "127.0.0.1";
    unsigned short port = 33333;
     
    int erreur;                             // Variable permettant de récupérer la valeur de retour des fonctions utilisées.
    int nbCaractere;                        // Indique le nombre de caractères qui a été reçu ou envoyé.
    SOCKET idSocket;                        // Identifiant de la socket.
    SOCKADDR_IN infoServeur;                // Déclaration de la structure des informations lié au serveur.
    char sendbuf[SIZEBUFFER];               // Buffer message envoi.
    char recbuf[SIZEBUFFER];                // Buffer message reception.
    int step = 0;                           // Gestion de la boucle LAFonction.
    int stepCon = 0;                        // Gestion pour savoir ou la connection/initialisation à planté pour savoir quoi fermer.
    short packetIDTmp = 1;                  // Valeur du packetID sauvegardé.
    char codeErreur[6];                     // Code erreur pour afficher dans la boite de dialogue.
    short cpt = 0;                          // Variable pour compter le nombre de fois que l'on passe dans la step 1 (initialisation)
    short paramOld[NBPARAM];                // Sauvegarde des params avant leurs modifs dans labView
    int cptReqStat = 0;                     // Compteur/Timer pour demander les status tout les X fois que l'on passe dans LAFonction
    // ********************************************************
    // Prototypes
    // ********************************************************
    __declspec(dllexport) void LAfonction(statMeasRead *cluster1, unsigned short paramLv[]);
    void connection(void);
    void sending(int action, int index, int value);
    void receive(statMeasRead *cluster1, unsigned short paramLv[]);
    void close(void);
    unsigned short checksum(unsigned short *addr, int len);
     
    // ********************************************************
    // LAFonction
    // ********************************************************
    __declspec(dllexport) void LAfonction(statMeasRead *cluster1, unsigned short paramLv[]){
     
      // Step = 0 -> Initialisation + connection.
      if(step == 0){
        connection();
      }
     
      // Step = 1 -> Recuperer tout les parametres.
      if(step == 1){
     
        sending(2, cpt, 0);
        receive(cluster1, paramLv);
     
        // Compteur de passage dans initialisation
        cpt++;
     
        // Initialisation terminee
        if(cpt == NBPARAM){
          memcpy((void *)paramOld, (const void*)paramLv, sizeof(paramLv));
          step = 2;
        }
      }
     
      //Step = 2 -> Envoyer et recevoir des données normalement.
      if(step == 2){
     
        // Boucle pour voir si le tableau des parametres a été modifié.
        for(cpt = 0; cpt < NBPARAM; cpt++){
          if(paramLv[cpt] != paramOld[cpt]){
            sending(3, cpt, paramLv[cpt]);
            receive(cluster1, paramLv);
            paramOld[cpt] = paramLv[cpt];
            break;
          }
        }
     
        // Status and Measures reading (TCS request)
        cptReqStat++;
        if(cptReqStat == 10){
          sending(1,0,0);
          receive(cluster1, paramLv);
          cptReqStat = 0;
        }
      }
     
      //Step = 3 -> Deconnection.
      if(step == 3){
        close(); 
      }           
    }
     
     
    // ********************************************************
    // Fonctions Connection
    // ********************************************************
    void connection(void){
     
      // Initialisation de Winsock
      erreur = WSAStartup(MAKEWORD(2,2), &initialisation_win32);
      if(erreur != 0){
        step = 3;
        sprintf(codeErreur,"%d",WSAGetLastError());
        MessageBox(NULL,codeErreur,"Erreur connexion : fonction WSAStartup() !",MB_OK|MB_ICONERROR);
      }
     
      // Ouverture d'une Socket
      idSocket = socket(AF_INET, SOCK_STREAM, 0);
      if(idSocket == INVALID_SOCKET){
        step = 3;
        stepCon = 1;
        sprintf(codeErreur,"%d",WSAGetLastError());
        MessageBox(NULL, codeErreur, "Erreur connexion : fonction socket() !",MB_OK|MB_ICONERROR);
      }
     
      // Etablissement de l'ouverture de session
      infoServeur.sin_family = AF_INET;
      infoServeur.sin_addr.s_addr = inet_addr(ip_adr); // Indiquez l'adresse IP de votre serveur  
      infoServeur.sin_port = htons(port);              // Port écouté du serveur 
     
      erreur = connect(idSocket, (struct sockaddr*)&infoServeur, sizeof(infoServeur));
      if(erreur != 0){
        step = 3;
        stepCon = 2;
        sprintf(codeErreur,"%d",WSAGetLastError());
        MessageBox(NULL,codeErreur, "Erreur connexion : fonction connect() !",MB_OK|MB_ICONERROR);
      }
      else{
        step = 1;
        stepCon = 3;
        MessageBox(NULL,"Vous êtes connecté avec le serveur","Client connecté !",MB_OK|MB_ICONASTERISK);
      }
    }
     
    // ********************************************************
    // Fonctions Send
    // ********************************************************
    void sending(int action, int index, int value){
     
      int size;
     
      // Status and Measures reading (TCS request)
      if(action == 1){
        // Création d'un pointeur vers la structure.
        struct statMeasReq *packet;
     
        // Allocation de la taille.
        packet = malloc(sizeof(struct statMeasReq));
     
        // Mise a zéro
        memset(packet, 0x0, sizeof(struct statMeasReq));
     
        // Garnissage.
        packet->control = 0x02;
        packet->lenght = 6;
        packet->checksum = 0;
        packet->packetID = packetIDTmp++;
        packet->checksum = checksum((unsigned short *)packet, packet->lenght);
     
        //Copie la structure dans le buffer
        memcpy((void*)sendbuf, (const void*)packet, packet->lenght);
     
        //Prend la taille du packet pour la transmettre a la fonction send.
        size = packet->lenght;
     
        //Libère la mémoire
        free(packet);
        packet = NULL;  
      }
     
      // Command or Parameter reading (TCS request)
      if(action == 2){
        // Création d'un pointeur vers la structure.
        struct commParaRead *packet;
     
        // Allocation de la taille.
        packet = malloc(sizeof(struct commParaRead));
     
        // Mise a zéro
        memset(packet, 0x0, sizeof(struct commParaRead));
     
        // Garnissage.
        packet->control = 0x12;
        packet->lenght = 6;
        packet->checksum = 0;
        packet->index = index;
        packet->checksum = checksum((unsigned short *)packet, packet->lenght);
     
        //Copie la structure dans le buffer
        memcpy((void*)sendbuf, (const void*)packet, packet->lenght);
     
        //Prend la taille du packet pour la transmettre a la fonction send.
        size = packet->lenght;
     
        //Libère la mémoire
        free(packet);
        packet = NULL;     
      }
     
      // Command or Parameter writing (TCS request)
      if(action == 3){
        // Création d'un pointeur vers la structure.
        struct commParaWrit *packet;
     
        // Allocation de la taille.
        packet = malloc(sizeof(struct commParaWrit));
     
        // Mise a zéro
        memset(packet, 0x0, sizeof(struct commParaWrit));
     
        // Garnissage.
        packet->control = 0x13;
        packet->lenght = 8;
        packet->checksum = 0;
        packet->index = index;
        packet->value = value;
        packet->checksum = checksum((unsigned short *)packet, packet->lenght);
     
        //Copie la structure dans le buffer
        memcpy((void*)sendbuf, (const void*)packet, packet->lenght);
     
        //Prend la taille du packet pour la transmettre a la fonction send.
        size = packet->lenght;
     
        //Libère la mémoire
        free(packet);
        packet = NULL; 
      }         
     
      nbCaractere = send(idSocket, sendbuf, size, 0);
     
      if(nbCaractere == SOCKET_ERROR){
        sprintf(codeErreur,"%d",WSAGetLastError());
        MessageBox(NULL,codeErreur, "Erreur send : fonction send() !",MB_OK|MB_ICONERROR);
     
        //Le serveur est mort, code erreur = 10054.
        if(strcmp(codeErreur,"10054") == 0) step = 3;
      }
      else memset(sendbuf, 0x0, sizeof(sendbuf));
    }
     
    // ********************************************************
    // Fonction Receive
    // ********************************************************
    void receive(statMeasRead *cluster1, unsigned short paramLv[]){
     
      int sel;
      fd_set read;
      struct timeval timeout;
      unsigned short saveChecksum;
      unsigned short returnChecksum;
     
      timeout.tv_sec = 0;
      timeout.tv_usec = 100000;
     
      FD_ZERO(&read);
      FD_SET(idSocket, &read);
     
      sel = select(idSocket + 1, &read, NULL, NULL, &timeout);
     
      // Probleme avec la fonction select.
      if(sel == SOCKET_ERROR){
        sprintf(codeErreur,"%d",WSAGetLastError());
        MessageBox(NULL,codeErreur, "Erreur receive : fonction select() !",MB_OK|MB_ICONERROR);
      }
     
      // Temps écoulé pour la fonction select.
      else if(sel == 0){
        //MessageBox(NULL,codeErreur, "Erreur receive : select() timeout!",MB_OK|MB_ICONERROR);
        //step = 3;
      }
     
      // Il y a un message a recuperer.
      else{
     
        //S'il y a une action a faire pour recv ... la fonction est faite
        if(FD_ISSET(idSocket, &read)){     
          nbCaractere = recv(idSocket, recbuf, MAXSIZEPACKET, 0);
     
          // Erreur lors de la fonction rec().
          if(nbCaractere==SOCKET_ERROR){
    	    sprintf(codeErreur,"%d",WSAGetLastError());
    	    MessageBox(NULL,codeErreur, "Erreur receive : fonction recv() !",MB_OK|MB_ICONERROR);
     
    	    //Le serveur est mort, code erreur = 10054.
    	    if(strcmp(codeErreur,"10054") == 0) step = 3;
          }    
          else{
    	    recbuf[nbCaractere]='\0'; // Permet de fermer le tableau après le contenu des data, car la fonction recv ne le fait pas
     
    	    // Creation du pointeur
    	    struct packetRec *packet;
     
    	    // Allocation de la taille.
    	    packet = malloc(sizeof(struct packetRec));
    	    packet->data = malloc(((recbuf[1])-6));
     
    	    // Mise à zero.
    	    memset(packet, 0x0, sizeof(struct packetRec));
     
    	    memcpy((void*)packet, (const void*)recbuf, nbCaractere);
     
    	    // Test du checksum.
    	    saveChecksum = packet->checksum;
    	    packet->checksum = 0;
    	    returnChecksum = checksum((unsigned short *)packet, packet->lenght);
     
    	    if(saveChecksum == returnChecksum) packet->checksum = saveChecksum;
     
    	    // Test du byte de control si checksum OK
    	    if(packet->checksum != 0){	
     
    	      // Status and Measures reading (PLC answer)
    	      if(packet->control == 0x02){
    	        /*struct statMeasRead *p;
    	        p = malloc(sizeof(struct statMeasRead));
                memset(p, 0x0, sizeof(struct statMeasRead));	        
    	        memcpy((void *)p, (const void*)recbuf, nbCaractere);*/
     
    	        memcpy((void *)cluster1, (const void*)recbuf, nbCaractere); 
     
    	        // Liberation de la mémoire
                /*free(p);
                p = NULL;*/ 
              }
     
    	      // Command/Parameter reading or writing (PLC answer)
    	      if(packet->control == 0x12 || packet->control == 0x17){       
                struct commParaReadWrit *p;
    	        p = malloc(sizeof(struct commParaReadWrit));
                memset(p, 0x0, sizeof(struct commParaReadWrit));	        
    	        memcpy((void *)p, (const void*)recbuf, nbCaractere);
     
    	        paramLv[p->index] = p->value;
    	        paramOld[p->index] = paramLv[p->index];
     
    	        // Liberation de la mémoire
                free(p);
                p = NULL;       
              }
     
    	      // PLC answer at a "parameter/command writing" request by "Last packet rejected"
    	      if(packet->control == 0x18){	        
                struct packetRejected *p;
    	        p = malloc(sizeof(struct packetRejected));
                memset(p, 0x0, sizeof(struct packetRejected));	        
    	        memcpy((void *)p, (const void*)recbuf, nbCaractere);
     
    	        // Liberation de la mémoire
                free(p);
                p = NULL; 
              }
            }
    	    else MessageBox(NULL,"Le calcule du checkSum à trouvé une erreur", "Erreur receive : fonction checksum() !",MB_OK|MB_ICONERROR);
     
    	    //Liberation de la mémoire.
    	    free(packet->data);
    	    packet->data = NULL;
            free(packet);
            packet = NULL;
            memset(recbuf, 0x0, sizeof(recbuf));                       
          }
        }
      }
    }
     
    // ********************************************************
    // Fonctions Close
    // ********************************************************
    void close(void){
     
      // Fermeture de la session TCP Correspondant à la commande connect()
      if(stepCon == 3){
        erreur = shutdown(idSocket, 2); // 2 signifie socket d'émission et d'écoute
        if(erreur != 0){
          sprintf(codeErreur,"%d",WSAGetLastError());
          MessageBox(NULL,codeErreur,"Erreur fermeture connexion : fonction shutdown() !",MB_OK|MB_ICONERROR);
        }
        else stepCon = 2;
      }
     
      // Fermeture de la socket correspondant à la commande socket()
      if(stepCon == 2){
        erreur = closesocket(idSocket);
        if(erreur != 0){
          sprintf(codeErreur,"%d",WSAGetLastError());
          MessageBox(NULL,codeErreur,"Erreur fermeture connexion : fonction closesocket() !",MB_OK|MB_ICONERROR);
        }
        else stepCon = 1;
      }
     
      // Quitte proprement le winsock ouvert avec la commande WSAStartup
      if(stepCon == 1){
        erreur = WSACleanup(); // A appeler autant de fois qu'il a été ouvert.
        if(erreur != 0){
          sprintf(codeErreur,"%d",WSAGetLastError());
          MessageBox(NULL,codeErreur,"Erreur fermeture connexion : fonction WSACleanup() !",MB_OK|MB_ICONERROR);
        }
        else{
          MessageBox(NULL,"Vous êtes deconnecté du serveur","Client deconnecté !",MB_OK|MB_ICONASTERISK);
          stepCon = 0;
          step = 0;
        }
      }
    }
     
    // ********************************************************
    // Calcule du checksum
    // ********************************************************
    unsigned short checksum(unsigned short *addr, int len){
     
      int nleft = len;
      unsigned short *w = addr;
      int sum = 0;
      unsigned short answer = 0;
     
      // Somme des données pris deux par deux.
      while (nleft > 1) {    
        sum += *w;
        w++;
        nleft -= 2;
      }
     
      // Calcule du complément à 1 sur 16bits.
      answer = ~sum;
     
      // Envoie de la valeur du checksum calculé.
      return (answer);
    }
    Cette DLL est inséré dans un VI LabView.


    Désolé de te faire perdre du temps avec mes demi réponses et demi questions.

    Mais je te remercie du temps que tu m'accordes !

  13. #13
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 69
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par nuFox Voir le message
    Le recv() n'est plus bloquant grace au select et un timeout court.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
      timeout.tv_sec = 0;
      timeout.tv_usec = 100000;
    Mon système est déjà au point et tourne parfaitement (enfin pour ce qu'il fait déjà)... C'est juste que ca ne rentre pas dans le principe de conception de programme de mon maitre de stage ... Et donc je dois modifier mon code, mais avant de le faire je me renseigne pour voir si c'est possible.
    Il faudrait déjà que la conception soit claire ! Si j'ai bien compris, il y a un problème avec l'utilisation des fonctions de la DLL et non les fonctions elle-mêmes...
    Si ca peut t'aider a y voir plus clair pour ne pas perdre de temps, voici mon code complet :
    Je vais regarder... C'est hyper-spécialisé (IP fixe, ports fixes), je ne sais pas si ça va tourner chez moi...

  14. #14
    Membre éclairé
    Inscrit en
    Février 2008
    Messages
    302
    Détails du profil
    Informations forums :
    Inscription : Février 2008
    Messages : 302
    Par défaut
    Bah le seul probleme qui reside pour le moment dans la DLL ...

    c'est le faite de savoir comment faire et ou placer la focntion recv() ...

    Moi j'ai mis une fonction recv() après chaque send() pour recuperer la réponse ...

    Mais mon maitre de stage veut que je ne fasse qu'un seul recv() mais au dessus en premier dans la fonction de la dll ...

    Comme on appelle une fonction de la dll de facon cyclique,
    recv(); <--|
    send(); ---|
    send(); ---|
    au premier passage le recv() sera en premier, mais au deuxieme passage le recv() va recup les paquets qui se trouvent sur la pile, enfin le pquet puisqu'il n'en prend qu'un a la fois. (j'espere avoir été clair cette fois si )

  15. #15
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 69
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par nuFox Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    recv(); <--|     
    send(); ---|
    send(); ---|
    au premier passage le recv() sera en premier,
    Comme je l'ai dit, si on ne fait pas de send() avant le recv() ça ne fonctionnera pas...

  16. #16
    Membre éclairé
    Inscrit en
    Février 2008
    Messages
    302
    Détails du profil
    Informations forums :
    Inscription : Février 2008
    Messages : 302
    Par défaut
    Citation Envoyé par Emmanuel Delahaye Voir le message
    Comme je l'ai dit, si on ne fait pas de send() avant le recv() ça ne fonctionnera pas...
    Et si on utiliser un select avec un timeout ? Comme dans le code source fournit ?

  17. #17
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 69
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par nuFox Voir le message
    Et si on utiliser un select avec un timeout ? Comme dans le code source fournit ?
    Bah, si tu veux, mais c'est une complication inutile...

  18. #18
    Membre éclairé
    Inscrit en
    Février 2008
    Messages
    302
    Détails du profil
    Informations forums :
    Inscription : Février 2008
    Messages : 302
    Par défaut
    Oky ! Merci de toute vos réponses ...

    A une prochaine fois ...
    (Et j'espere que cette prochaine fois je ferais un post un peu plus clair avec tout les éléments dés le départ ... Et encore désolé )

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

Discussions similaires

  1. Réponses: 8
    Dernier message: 30/09/2010, 22h25
  2. [classe ou fonction] fonction magic number ?
    Par Leinad dans le forum Langage
    Réponses: 13
    Dernier message: 28/07/2006, 18h58
  3. [fonction] fonction pour formatage texte
    Par titiyo dans le forum Delphi
    Réponses: 5
    Dernier message: 29/06/2006, 13h16
  4. [FONCTION] fonction VBA
    Par heavenvibes dans le forum Access
    Réponses: 1
    Dernier message: 26/06/2006, 09h42
  5. [Fonction] fonction mysql_connect non reconnue
    Par Invité dans le forum SQL Procédural
    Réponses: 6
    Dernier message: 20/02/2006, 19h47

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