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 :

Probleme de calcule dans une fonction


Sujet :

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 Probleme de calcule dans une fonction
    Bonjour ... merci deja de lire mon problème ...

    Alors voila je vous explique, je dois réaliser le calcule d'un checksum et donc pour ca j'ai créé une fonction pour le faire.
    Vous allez me demander "Calculer un checksum sur quoi?" ... Et bien calculer le checksum sur un "paquet" que j'ai recu par le protocole TCP ! pour voir si le checksum que je calcule correspond bien au checksum present dans le paquet (qui a été calculer par l'envoyeur du "paquet") ... Bon j'espere que les aboutissent auront bien été expliqué ...

    Alors voici la fonction de calcule de checksum:
    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
     
    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);
    }
    Voici l'appelle a la fonction checksum :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    checksum((unsigned short *)packet, packet->lenght);
    Et voici la structure du paquet :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    struct packetRec{
      char control;
      char lenght;
      unsigned short checksum;
      unsigned short id;
      char *data;    
    };
    ainsi que ca déclaration :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    //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);
    (recbuf étant le buffer de reception de la fonction recv(); )

    Voici un exemple de paquet que je recois (7773 correspond au checksum)
    Receive: 2 94 7773 1 1 2 F9EC FA0E 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 98 FFF4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0


    Alors voila, le probleme est que ca fonctionne pour des petits paquets ... Dans le sens ou il ne depasse pas 14Bytes ... Mais une fois que le paquet est plus gros CAD 148Bytes et bien le checksum ne retrouve pas la valeur calculer de l'autre cote (qui est la bonne ... Puisque je l'ai calculer a la main) ... J'ai affiché la valeur que j'obtenais et donc j'obtien FFFF (65535) ...

    Et donc voila ... Je me demandais si vous sauriez d'ou vient le probleme ... j'espere avoir été clair et conci dans l'explication de mon probleme ...


    Merci d'avance.

  2. #2
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    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 395
    Par défaut
    1. La checksum n'est-elle pas supposée être limitée aux data ?
    2. Fais gaffe à l'endianness de la checksum que tu calcules...
    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.

  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
    Non le checksum porte sur tout le paquet (pour pouvoir verifier son integrité a la reception) ... Je ne construit pas un paquet TCP mais juste les données que je vais inclure dans la trame TCP ...

    Et oui j'ai fais attention aux indiens ^^ ...

    De plus ca fonctionne pour les petit paquet mais pas pour les gros ...
    La preuve :
    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
     
    Calculé	Recu
    62442	62442
    62445	62445
    62444	62444
    62443	62443
    62442	62442
    61340	61340
    62433	62433
    59162	59162
    32437	32437
    40575	40575
    62435	62435
    62434	62434
    62433	62433
    62432	62432
    65535	30579 <--- Correspond au calcule du checksum du plus gros paquet

    Pour info voici aussi la declaration de recbuf :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    #define SIZEBUFFERR 160
    char recbuf[SIZEBUFFERR];

  4. #4
    Membre chevronné Avatar de corentin59
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    462
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 462
    Par défaut
    question peut-être bête mais qui vaut le coup d'être posée : n'as-tu pas un problème de dépassement de la plus grande valeur pouvant être codée sur un unsigned short ? Remplace les "short" par des "long" pour voir.

  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
    Pour le retour du checksum(unsigned short answer) ? Justement le but est de reduire la valeur de la somme (int donc 32bits) dans un unsigned short (16bits) ... Donc c'est sur que ca va depasser mais ce n'est pas grave ... enfin du moin je pense

    Sinon si c'est pas pour checksum tu parlais de quoi ?

  6. #6
    Membre éclairé
    Inscrit en
    Février 2008
    Messages
    302
    Détails du profil
    Informations forums :
    Inscription : Février 2008
    Messages : 302
    Par défaut
    Pas d'autre suggestion ?

  7. #7
    Membre chevronné Avatar de corentin59
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    462
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 462
    Par défaut
    pourrais-tu donner le paquet pour lequel tu as un problème, pour qu'on puisse faire nos essais de notre côté ?

  8. #8
    Membre éclairé
    Inscrit en
    Février 2008
    Messages
    302
    Détails du profil
    Informations forums :
    Inscription : Février 2008
    Messages : 302
    Par défaut
    Voici le packet :
    Receive: 2 94 7773 1 1 2 F9EC FA0E 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 98 FFF4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

    et voici la fonction de log pour que tu t'y retrouve

    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
     
    void logpacket(char tab[], int size, int code){
     
         FILE * log = NULL;
         int j;
     
         log = fopen("LogPacket.csv", "a");
         if(log != NULL){     
           if(code == 1){
             fprintf(log, "%s;", "Send:");
             for(j=0; j<size; j++){    
               if(j == 0 || j == 1) fprintf(log,"%hhX;", (unsigned char)tab[j]);
               else{
                 fprintf(log, "%hhX;", (unsigned char)tab[j]+(256*(unsigned char)tab[j+1]));
                 j++;           
               }
             }
           }
           if(code == 2){
             fprintf(log, ";->;%s;", "Receive:");
             for(j=0; j<size; j++){    
               if(j == 0 || j == 1) fprintf(log,"%hhX;", (unsigned char)tab[j]);
               else{
                 fprintf(log, "%hhX;", (unsigned char)tab[j]+(256*(unsigned char)tab[j+1]));
                 j++;           
               }
             }
             fprintf(log,"\n");        
           }
         }
         fclose (log);
    }
    et l'appelle a la fonction log (temps qu'a faire ...) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    logpacket(recbuf, nbCaractere, 2);
    Merci en tout cas ... Moi aussi de mon coté, j'ai refais une application qui ne fait que le calcule du checksum ... Mais pour l'instant c'est pas fameux ... Sauf peut etre que j'ai remarqué que dans l'appelle a la fonction checksum que packet->lenght donnait -108 hors il devrait donner 148 .. Peut etre est ce une piste ... Mais j'ai essayé en metant nbCaractere qui vaut lui 148 et rien n'a faire ca donne pas la bonne réponse

  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
    Haaaaaaaaaa .... Enfait ... C'est le malloc je pense

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    packet->data = malloc(((recbuf[1])-6));
    C'est ligne est censée me donner la taille des données ... Tout les paquets que je recoit ont la "meme entete" CAD 6 Bytes qui sont commun a tout les paquet et c'est juste ce que je met dans data qui varie ...

    La valeur dans recbuf[1] est la taille de mon paquet ... Donc pour savoir la taille de data, je prend la valeur de cette case et je retire 6 ... Avec une taille de 148 (donc la taille du grand paquet), ca me donne une valeur de -114 ... et quand j'essaie avec de par exemple 14 (taille d'un petit paquet) et bien il me renvoie bien 8 ... Donc je pense que le probleme pourrait etre lier a ca ... Hors je ne vois pas trop comment regler le probleme ... Puisque le calcule pour le malloc fonctionne a moitié :s

  10. #10
    Membre éclairé
    Inscrit en
    Février 2008
    Messages
    302
    Détails du profil
    Informations forums :
    Inscription : Février 2008
    Messages : 302
    Par défaut
    Et bien ca n'a pas l'air d'etre ca ...

    ca me retourne toujours 65535
    au lieu de 30579
    pour le paquet donné ;(

  11. #11
    Membre chevronné Avatar de corentin59
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    462
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 462
    Par défaut
    le tableau d'unsigned short sur lequel pointe addr est un tableau qui contient la valeur correspondant aux caractères dans ton paquet (0 pour 0, 10 pour A et 15 pour F) ?

    len correspond au nombre de ces valeurs ? si oui, pourquoi tu parles de 148, il n'y a pas 148 caractères dans le paquet que tu donnes.

  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
    Enfait c'était a l'appelle de la fonction checksum ...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    returnChecksum = checksum((unsigned short *)packet, packet->lenght);
    Dans packet->lenght se trouvait la valeur -114 ... Donc il ne faisait pas les calcule donc l'inversion de 0 ca faisait tout des F d'ou la valeur ...

    Donc je l'ai remplacé par :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    returnChecksum = checksum((unsigned short *)packet, nbCaractere);
    Hors maintenant la question que je me pose, c'est pourquoi il met -114 dans packet->lenght ? :s

  13. #13
    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 corentin59 Voir le message
    le tableau d'unsigned short sur lequel pointe addr est un tableau qui contient la valeur correspondant aux caractères dans ton paquet (0 pour 0, 10 pour A et 15 pour F) ?

    len correspond au nombre de ces valeurs ? si oui, pourquoi tu parles de 148, il n'y a pas 148 caractères dans le paquet que tu donnes.
    C'est pour 148 cellule ...
    Et il pointe vers un tableau qui contient le message que j'ai recu ... et je l'affiche en hexa pour avoir plus facile ...


    Mais ca va j'ai trouvé ^^

  14. #14
    Membre chevronné Avatar de corentin59
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    462
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 462
    Par défaut
    je ne sais pas car tu n'a pas donné la ligne de code qui définit packet->lenght.

    Ceci dit, dans ton programme, tu manipules des int, des char, des unsigned char, des unsigned short, ... Il y a peut-être une confusion à un moment

  15. #15
    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 corentin59 Voir le message
    le tableau d'unsigned short sur lequel pointe addr est un tableau qui contient la valeur correspondant aux caractères dans ton paquet (0 pour 0, 10 pour A et 15 pour F) ?

    len correspond au nombre de ces valeurs ? si oui, pourquoi tu parles de 148, il n'y a pas 148 caractères dans le paquet que tu donnes.
    C'est pour 148 cellule ...
    Et il pointe vers un tableau qui contient le message que j'ai recu ... et je l'affiche en hexa pour avoir plus facile ...


    Mais ca va j'ai trouvé ^^ enfin pour ca ... now j'me pose une autre question ... (cf plus haut)

  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 corentin59 Voir le message
    je ne sais pas car tu n'a pas donné la ligne de code qui définit packet->lenght.

    Ceci dit, dans ton programme, tu manipules des int, des char, des unsigned char, des unsigned short, ... Il y a peut-être une confusion à un moment
    le packet-> se definit avec le memcpy du buffer dans la structure de packet ... Il remplit les champs automatiquement

  17. #17
    Membre chevronné Avatar de corentin59
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    462
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 462
    Par défaut
    Citation Envoyé par nuFox Voir le message
    le packet-> se definit avec le memcpy du buffer dans la structure de packet ... Il remplit les champs automatiquement
    je pense qu'il y a un problème justement ici. Ta structure paquet contient deux char, deux unsigned short et un pointeur sur un char. ton tableau data n'a aucune raison d'être à la suite, dans la mémoire, de ta structure. De plus, le memcpy va copier des char (recbuf) sur des char et des unsigned short et sur le pointeur, et ... En fonction de la valeur de nbcaratère

    Essaies de fixer les valeurs à la main sans utiliser de mem???, pour voir

  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
    Citation Envoyé par corentin59 Voir le message
    je pense qu'il y a un problème justement ici. Ta structure paquet contient deux char, deux unsigned short et un pointeur sur un char. ton tableau data n'a aucune raison d'être à la suite, dans la mémoire, de ta structure. De plus, le memcpy va copier des char (recbuf) sur des char et des unsigned short et sur le pointeur, et ... En fonction de la valeur de nbcaratère

    Essaies de fixer les valeurs à la main sans utiliser de mem???, pour voir

    Ha merde ... COmment peut on faire pour etre sur que la chaine de caractere data soit a la suite de la structure dans la mémoire ?

    Parce que le faite de copier des char dans des unsigned short c'est pas spécialement grave, puisque je copie une zone de mémoire ... Donc il decoupera les info's en fonction des variable definie (enfin je pense ... Puisque ca marche :s )

  19. #19
    Membre chevronné Avatar de corentin59
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    462
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 462
    Par défaut
    au lieu de faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    memcpy((void*)packet, (const void*)recbuf, nbCaractere);
    ne peux-tu pas faire quelquechose du genre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    int i;
    struct packetRec *packet;    
    packet = malloc(sizeof(struct packetRec));
    packet->data = malloc(((recbuf[1])-6)); // il y a peut-être un +1 à mettre pour le '\0' final ?
    // verifier que les mallocs se sont bien passés
    packet->control = recbuf[0];
    packet->length = recbuf[1];
    packet->checksum = (unsigned short) (256 * recbuf[2] + recbuf[3]); // ou dans l'autre sens
    packet->id = (unsigned short) (256 * recbuf[4] + recbuf[5]); // ou dans l'autre sens
    strcpy(packet->data,recbuf[6]);

  20. #20
    Membre éclairé
    Inscrit en
    Février 2008
    Messages
    302
    Détails du profil
    Informations forums :
    Inscription : Février 2008
    Messages : 302
    Par défaut
    Si, je peux le faire ... Je vais essayé ... Ca rendrait le programme plus stable ? Parce que la dans l'état actuel des choses, le programme tourne bien

Discussions similaires

  1. [XL-2010] Modifier application.calculation dans une fonction ?
    Par zanimox dans le forum Macros et VBA Excel
    Réponses: 6
    Dernier message: 14/10/2013, 15h17
  2. [MySQL] Probleme de variable dans une fonction
    Par termi78 dans le forum PHP & Base de données
    Réponses: 7
    Dernier message: 03/05/2012, 17h03
  3. Probleme de comptage dans une fonction
    Par kev484 dans le forum Débuter
    Réponses: 4
    Dernier message: 18/09/2008, 12h57
  4. Réponses: 6
    Dernier message: 24/11/2007, 18h48
  5. Probleme valeur de parametre dans une fonction
    Par TitouLolo dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 19/05/2005, 13h56

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