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 :

Socket : buffer envoyé != buffer reçu


Sujet :

Réseau C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Avril 2006
    Messages : 107
    Par défaut Socket : buffer envoyé != buffer reçu
    Bonjour à tous !
    Voila, j'ai un souci avec l'envoi d'un buffer de données par socket tcp/ip.
    J'ai une caméra (cliente) qui prend des images pgm, les converties en jpeg et les envois au serveur (pc). Mais le buffer reçu est différent de celui envoyé !

    code du client (caméra) qui envoit l'image :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
        //sauvegarde de l'image dans un fichier
                    FreeImage_Save(FIF_JPEG, check, "imageprise.jpg", JPEG_DEFAULT);
                    // encode and save the image to the memory
                    FreeImage_SaveToMemory( FIF_JPEG, check, hmemjpeg, JPEG_DEFAULT );
                    int jpeg_size = (int) FreeImage_TellMemory(hmemjpeg);
                    std::cout	<< "taille du jpeg : " << jpeg_size << std::endl;
                    //
                    // Envoit du buffer :
                    //
                    p->sendInteger( jpeg_size, sizeof(int) );
                    p->send( (const char*) hmemjpeg, jpeg_size );

    code du serveur qui reçoit l'image :
    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
     
    #define CENT_KILO 102400
        unsigned char *reception = new unsigned char[CENT_KILO];
        cout << "Allocation mémoire : ok " << endl;
     
    ....
     
                //attente de données pendant 5 secondes
                p->waitData(5) ;
                //reception de la taille du fichier jpeg :
                p->receiveInteger( intsize, &jpegfilesize, &recu);
                //reception du fichier :
                p->receive(jpegfilesize, reception , &sz);
                cout << "Image n°"<< i <<"  Taille reçue : "<< sz <<"     Taille attendue : "<<  jpegfilesize << endl;
                // écriture dans un fichier :
                FILE *stream = fopen("buffer.jpg", "wb");
                if(stream) {
                    fwrite( reception, sizeof(BYTE), jpegfilesize, stream);
                    fclose(stream);
                }
     
    ....
    delete[] reception;
    Voila, l'envoit se passe bien :
    Client:
    Serveur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Image n°0  Taille reçue : 68859     Taille attendue : 68859

    Mais les données reçues sont différentes :
    données envoyées par la caméra (fichier imageprise.jpeg)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     00000000:  ff d8 ff e0 00 10 4a 46  49 46 00 01 01 01 00 48  ......JFIF.....H
     00000010:  00 48 00 00 ff db 00 43  00 08 06 06 07 06 05 08  .H.....C........
     00000020:  07 07 07 09 09 08 0a 0c  14 0d 0c 0b 0b 0c 19 12  ................
     00000030:  13 0f 14 1d 1a 1f 1e 1d  1a 1c 1c 20 24 2e 27 20  ........... $.' 
     00000040:  22 2c 23 1c 1c 28 37 29  2c 30 31 34 34 34 1f 27  ",#..(7),01444.'
     00000050:  39 3d 38 32 3c 2e 33 34  32 ff c0 00 0b 08 04 0e  9=82<.342.......
     00000060:  05 6c 01 01 11 00 ff c4  00 1f 00 00 01 05 01 01  .l..............
     00000070:  01 01 01 01 00 00 00 00  00 00 00 00 01 02 03 04  ................
     00000080:  05 06 07 08 09 0a 0b ff  c4 00 b5 10 00 02 01 03  ................
     00000090:  03 02 04 03 05 05 04 04  00 00 01 7d 01 02 03 00  ...........}....
    buffer reçu par le pc (fichier buffer.jpeg)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    00000000:  10 05 d0 00 10 04 dd 70  00 00 00 10 00 00 00 19  .......p........
     00000010:  00 00 00 00 10 05 bd 28  00 00 00 00 00 00 00 00  .......(........
     00000020:  2a af 29 28 00 00 00 19  00 00 00 01 10 05 8e 68  *.)(...........h
     00000030:  10 04 d4 18 10 05 bd 28  2a af 28 78 00 00 00 19  .......(*.(x....
     00000040:  00 00 00 01 2a af 55 38  10 04 f9 40 10 04 ef 50  ....*.U8...@...P
     00000050:  2a ae 76 00 00 00 00 19  00 00 00 01 10 05 63 78  *.v...........cx
     00000060:  10 05 6f 90 10 05 63 a8  2a ae 6e 60 00 00 00 19  ..o...c.*.n`....
     00000070:  00 00 00 00 10 04 d5 20  00 00 00 00 00 00 00 00  ....... ........
     00000080:  2a ad 10 40 00 00 00 19  00 00 00 00 10 04 d5 e0  *..@............
     00000090:  00 00 00 00 00 00 00 00  2a af 29 28 00 00 00 19  ........*.)(....
     000000a0:  00 00 00 01 2a ae fc 00  10 04 d5 20 10 04 d5 e0  ....*...... ....
    Voila, c'est la première fois que je fais des socket en C++ et je ne comprend pas ce qu'il se passe !

    fonction d'envois :
    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
     
    void ProtocoleTCP::send(const char *data, const unsigned int size) throw (CSocketError){
            if (connecte){
                /*La fonction boucle pour envoyer le nombre d'octets demandés */
                int nb=0;
                for (unsigned int i=0; i<size; i+=nb){
                    /*envois des données*/
    #ifdef CLIENT
                    //client envoit au serveur
                    nb= ::send(sock, data+i, size, 0);
    #else
                    //serveur envoit au client
                    nb= ::send(csock, data+i, size, 0);
    #endif
                    if (nb == SOCKET_ERROR) throw CSocketError("Impossible d'envoyer les données sur la socket !");
                }
            }
            else std::cout 	<< "La connexion n'est pas établie !" << std::endl;
        }
    et de reception :
    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
     
    void ProtocoleTCP::receive(const unsigned int size, unsigned char* buf, size_t *buf_size)
            throw (CSocketError) {
                if (connecte){
    #define MAX_OCTETS 10240
                    int nb;
                    std::string msg;
                    for(size_t i=0; i < size ; i+= nb) {
                        char* recpt=new char[MAX_OCTETS];
                        // On reçoit les données par paquets maximum de MAX_OCTETS
    #ifdef CLIENT
                        //client recoit du serveur
                        nb=recv(sock, recpt, (size_t) ( (size-i-1)%MAX_OCTETS+1 ), 0);
    #else
                        //serveur recoit du client
                        nb=recv(csock, recpt, (size_t) ( (size-i-1)%MAX_OCTETS+1 ), 0);
    #endif
                        //std::cout	<< "Recut "<<nb<<" octets!" << std::endl;
                        recpt[nb]='\0';
                        //std::cout	<< "Recpt : " << std::string(recpt) << std::endl;
                        // Si on a rien reçut, on arrete
                        if(nb == 0) {
                            *buf_size=0;
                            std::cout	<< "Pas de données à lire!" << std::endl;
                            return;
                        }
                        // Vérification d'erreur
                        if(nb < 0) throw CSocketError("Erreur lors de la réception sur la socket !");
                        // Concaténation du paquet reçut avec le reste du message.
                        msg += std::string(recpt, nb);
                        delete[] recpt;
                    }
                    *buf_size=msg.size();
                    memcpy( (char *)buf, msg.c_str(), *buf_size);
                }
                else std::cout	<< "La connexion n'est pas établie !" << std::endl;
            }

    Merci pour votre aide !

  2. #2
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Par défaut
    Note aux futurs lecteurs :
    Le langage n'est pas du C mais du C++. Le problème est plus réseau que langage, c'est pourquoi le message est dans ce forum.
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  3. #3
    Invité(e)
    Invité(e)
    Par défaut
    Bonjour,

    Deux remarques :

    • En émission, on envoie un handle hmemjpeg, qu'on essaie d'enregistrer tel quel en réception. Cela est il valable ?

    Pour le savoir, il faudrait d'abord enregistrer ce fichier sur le serveur avant de l'envoyer.

    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
    //sauvegarde de l'image dans un fichier
    FreeImage_Save(FIF_JPEG, check, "imageprise.jpg", JPEG_DEFAULT);
    // encode and save the image to the memory
    FreeImage_SaveToMemory( FIF_JPEG, check, hmemjpeg, JPEG_DEFAULT );
    int jpeg_size = (int) FreeImage_TellMemory(hmemjpeg);
    std::cout	<< "taille du jpeg : " << jpeg_size << std::endl;
    std::cout << "test enregistrement" << std::endl;
    FILE *stream = fopen("buffer.jpg", "wb");
    if(stream) {
        fwrite( hmemjpeg, 1, jpeg_size, stream);
        fclose(stream);
    } else {
        perror("buffer.jpg");
    }
     
    //
    // Envoi du buffer :
    //
    p->sendInteger( jpeg_size, sizeof(int) );
    p->send( (const char*) hmemjpeg, jpeg_size );
    et vérifier que les fichiers buffer.jpg et imageprise.jpg sont équivalents.

    Si les fichiers sont différents, il faudra faire un choix : soit lire et envoyer intégralement le fichier imageprise.jpg, soit envoyer le handle hmemjpeg et l'utiliser comme un handle côté réception.

    Pour ma part, la première façon semble plus simple... et réutilisable pour d'autres types de fichiers.



    • Deuxième point : la réception.
    La réception se fait avec une std::string, or un fichier jpg est binaire, il y a donc risque d'avoir des mauvaises interprétation des caractère '\0'.

    Je pense que l'enregistrement devrait se faire au fur et à mesure de la réception des paquets :
    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
    FILE *stream = fopen("buffer.jpg", "wb");
    if(NULL == stream) {
        perror("buffer.jpg");
        return;
    }
    for(size_t i=0; i < size ; i+= nb) {
        char recpt[MAX_OCTETS];
        // On reçoit les données par paquets maximum de MAX_OCTETS
        #ifdef CLIENT
        //client recoit du serveur
        nb=recv(sock, recpt, MAX_OCTETS, 0);
        fwrite( recpt, 1, nb, stream);
        #endif
    }
    fclose(stream);

  4. #4
    Membre éprouvé
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Avril 2006
    Messages : 107
    Par défaut
    Tout d'abord, merci pour ton aide !

    Tu as vu juste, le problème ne vient pas des fonctions d'envois/receptions, puisque le fichier enregistré sur la caméra est bien strictement le même que celui reçut par le pc (commande diff).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    std::cout << "test enregistrement" << std::endl;
    FILE *stream = fopen("buffer.jpg", "wb");
    if(stream) {
        fwrite( hmemjpeg, 1, jpeg_size, stream);
        fclose(stream);
    } else {
        perror("buffer.jpg");
    }
    Le problème vient donc de l'écriture tel quel du handle, qui n'est pas valable.

    Comme sur la caméra la lecture/écriture répétée est à bannir, j'essaie donc de récupérer le handle coté réception par ce code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     p->waitData(5) ;
                //reception de la taille du fichier jpeg :
                p->receiveInteger( intsize, &jpegfilesize, &recu);
                //reception du fichier :
                p->receive(jpegfilesize, reception , &sz);
                cout << "Image n°"<< i <<"  Taille reçue : "<< sz <<"     Taille attendue : "<<  jpegfilesize << endl;
     
                // get the buffer from the memory stream
                FIMEMORY *jpegmem = FreeImage_OpenMemory( reception, jpegfilesize);
                // get the file type
                FREE_IMAGE_FORMAT fif = FreeImage_GetFileTypeFromMemory(jpegmem, 0);
                std::cout	<< "Image format : " << fif << std::endl;
    Et là j'ai un beau -1 pour dire format inconnu.... alors que le buffer reçu est bien identique à celui envoyé....
    Peut être un problème d'alignement de structures....
    Enfin bon, ce n'est plus un problème réseau, je vais chercher.

    Merci encore pour ton aide.

  5. #5
    Membre éprouvé
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Avril 2006
    Messages : 107
    Par défaut
    Je poste la solution à mon problème : envoyer l'image jpeg (convertie grâce à la lib FreeImage) par socket sans avoir à l'écrire dans un fichier.
    (En effet ça n'as plus rien à voir avec un problème de réseau, mais on sais jamais, ça peut être utile... )

    J'ai du chercher dans le code de la librairie pour trouver le pointeur sur l'image jpeg :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    p->send( (const char *) ((FIMEMORYHEADER *) hmemjpeg->data)->data, jpeg_size );
    (Il faut avoir inclu le fichier FreeImageIO.h )
    Là l'image jpeg est envoyée, et on la récupère du coté serveur. On pourra ainsi l'écrire dans un fichier, ou alors la récupérer avec une autre librairie : CImg et son plugin jpeg_buffer par exemple.

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

Discussions similaires

  1. [Socket][File] Envoyer un tableau de byte
    Par itsmii dans le forum Entrée/Sortie
    Réponses: 14
    Dernier message: 30/01/2014, 09h10
  2. Socket effacer le Buffer
    Par ralf91 dans le forum C
    Réponses: 4
    Dernier message: 21/01/2012, 12h32
  3. Socket: Tailles des buffers en émission et réception
    Par rulianf dans le forum Réseau
    Réponses: 0
    Dernier message: 17/02/2010, 16h01
  4. Socket : augmenter le buffer de sortie
    Par Gomoz dans le forum C#
    Réponses: 0
    Dernier message: 26/01/2010, 19h12
  5. Socket, C++ et buffer !
    Par agent007se dans le forum C++
    Réponses: 9
    Dernier message: 18/04/2006, 18h02

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