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++Builder Discussion :

Récupérer une image avec un socket?


Sujet :

C++Builder

Vue hybride

sfn84 Récupérer une image avec un... 10/04/2011, 16h39
themadmax Je ne maitrise pas C++... 10/04/2011, 18h13
ShaiLeTroll Pourquoi un socket pour un... 11/04/2011, 10h04
sfn84 Tout d'abord merci grandement... 11/04/2011, 20h51
sfn84 Voici les instructions que... 11/04/2011, 21h03
Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2011
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vaucluse (Provence Alpes Côte d'Azur)

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

    Informations forums :
    Inscription : Janvier 2011
    Messages : 19
    Par défaut Récupérer une image avec un socket?
    Bonjour,

    je suis sur un projet informatique et j'essaie de récupérer une image sur un serveur (en http). Je développe sur l'ide c++ builder 6..
    j'utilise un socket afin de récupérer l'image en mémoire dans un flux, mais j'ai un problème:
    Lorsque j'utilise la fonction ReceiveLenght je n'arrive pas à recevoir la bonne taille de trame. Le serveur m'envoie une trame PLUS longue que ce que me retourne ReceiveLength.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    void __fastcall TForm1::SocRead(TObject *Sender, TCustomWinSocket *Socket)
    {  
            int nReceived = Socket->ReceiveLength(); // nombre d'octets reçus
            char buffer[102000]; // buffer de récupération des paquets venant du serveur
     
            Socket->ReceiveBuf(buffer, nReceived);  // lis que les 200 premier caractères la plupart du temps
            pStream->Write(buffer, nReceived );       // transférer dans le stream
                                                  // pour traitement ultérieur
    }
    L'avantage c'est que je reçois bien des données, et j'ai vérifier avec le débogueur je reçois les bonnes données [trame réponse + données (image)].
    Néanmoins, je ne reçois quasiment jamais la trame complète à cause de ce problème. Est-ce que vous savez comment résoudre ce problème? avez vous une autre méthode de réception d'une image à me proposer?

    Je suis preneur sur toutes les solutions que vous pourriez me proposer.
    J'attends avec impatience vos réponses, merci !

  2. #2
    Membre chevronné Avatar de themadmax
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    446
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 446
    Par défaut
    Je ne maitrise pas C++ buider, mais pour la programmation réseaux j'utilise courrament les outils comme wireshark et le plugin firefox LiveHTTPheaders. Wireshark (anciennement ethereal) te permet de sniffer toutes les trames de ton ordi, ce qui permet de comprendre debugger finement les échanges réseaux. L'outil telnet peut aussi te permettre d'envoyer des requettes à un serveur HTTP, et d'afficher le retour.

  3. #3
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 081
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 081
    Par défaut
    Pourquoi un socket pour un server HTTP ?
    Tu ne pouvais pas faire un GET\POST via un THTTPRio ou un TIdHTTP ?

    Sinon, c'est tout à fait normal, j'ai fait l'équivalent en Delphi, mon code est simpliste mais lorsque tu as une connexion client qui récupère une trame depuis un Serveur, ça passe si il y a une pause entre deux images

    En général, tu vas recevoir, avec les composant TClientSocket, des paquets de 8Ko, cela correspond en général au tampon de la carte Ethernet (et à l'implémentation du TCP\IP de l'OS), une fois plein, c'est l'OS qui récupère le paquet et signal au socket de lire les données, pendant ce temps, la carte continue a recevoir de données, le tampon se remplit, l'OS le récupère, je ne sais pas si il y a une limite évidemment dans l'OS de paquets stockés, si le client ne lit pas la socket assez régulièrement de dépasser le tampon de windows, je ne sais pas ce qui se passe à ce moment, je ne l'ai jamais tenté !

    Par conséquent, tu dois manuellement accumulé les suite de paquet de 8Ko jusqu'à ce qu'il n'y ait plus de données !
    En général, tu sais qu'un stream se termine par un pacquet d'une taille inférieure à 8Ko, puis un paquet de taille zéro indiquant la fin d'un stream, puis le stream suivant reprend un cycle de paquet de 8Ko...

    Il arrive que deux stream arrivent de façon très rapproché, et là cela peut poser problème car tu ne sais pas où se termine le premier message et où commence le second message

    Voici deux sujets (attention, il y a de nombreux liens vers d'autres sujets, la lecture de l'ensemble pourrait t'aider à mieux comprendre le protocol TCP\IP)
    Envoi donnes par socket
    Socket et envoi d'image
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  4. #4
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2011
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vaucluse (Provence Alpes Côte d'Azur)

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

    Informations forums :
    Inscription : Janvier 2011
    Messages : 19
    Par défaut
    Tout d'abord merci grandement pour votre attention face à mon soucis

    J'ai réussi à palier mon problème de base: il suffisait juste de récupérer la valeur de retour de la fonction ReceiveBuf et non ReceiveLength !

    Effectivement ReceiveLength est assez mal foutu elle retourne pas les bonnes valeurs tout le temps. j'ai tout simplement fait cela:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    void __fastcall TForm1::SocRead(TObject *Sender, TCustomWinSocket *Socket)
    {
            char buffer[102000]; // buffer de recuperation des paquets venant du serveur
     
            int nbLu = Socket->ReceiveBuf(buffer, 102000 );  // lire les paquets
            pStream->Write(buffer, nbLu);       // transferer dans le stream
                                                  // pour traitement ulterieur
    }
    J'avais mal étudié la doc de borland .
    Par contre maintenant j'essaie de décoder cette trame et c'est pas gagner.
    J'isole le contenu de l'image et j'essaie de l'afficher sur mon IHM mais ça me met une erreur de jpeg: 'JPEG error #41'. -> Je me suis pourtant assurer d'isoler la partie de la réponse [de FFD8(début jpg) à FFD9(fin jpg)]...

    ShaiLeTroll, j'utilise un socket parce que je ne sais pas faire autrement. J'ai utilisé un TNMHTTP mais je n'arrivais pas à traiter l'image en mémoire (j'étais obligé de l'enregistrer sur mon disuqe dur).

    SI tu as une méthode plus simple avec les composants que tu as cités je suis preneur. Un exemple d'utilisation par exemple?

    Merci encore pour tout !

  5. #5
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2011
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vaucluse (Provence Alpes Côte d'Azur)

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

    Informations forums :
    Inscription : Janvier 2011
    Messages : 19
    Par défaut
    Voici les instructions que j'utilise:

    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
     
    i = 0, j = 0;
        int comp;
        unsigned char var[4], var2[4]="ÿØÿþ", tab;      // ÿØÿþ=FFD8.... 
     
        pStream->Position = 2;  
        while(pStream->Read(var,4)){
            i+=4;
            comp = strncmp(var,var2,4);
            if(comp == 0) break;
        }
        i-=2;
        pStream->Position = i;
        pStream->Read(var,4);
        pStream->Position = 0;
        while(pStream->Read(&tab,2)){
            j+=2;
            if(!strncmp(&tab,"ÿ",2)){
              pStream->Read(&tab,2);
              j+=2;
              if(!strncmp(&tab,"Ù",2)){
                break;                  //si on a FFD9 on quitte 
              }
            }
        }
        tailleImage = j - i;    //déclaré dans le .h
     
        DisplayImage();   //traite et affiche l'image
    Et voici le contenu de la fonction DisplayImage :

    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
     
      TJPEGImage* jp = new TJPEGImage;      // necessite //"jpeg.hpp"
      unsigned char buf[100000];
     
     
      try
      {
        pFluxImage->Position = 0;
        pStream->Position = i;// debut code jpeg après le Header dans le stream
        pStream->Read(buf, tailleImage);
        pFluxImage->Write(buf, tailleImage);
        jp->LoadFromStream(pFluxImage);     // charger le jpeg converti en bitmap
        Image1->Picture->Assign(jp); // afficher l'image
        Application->ProcessMessages();  //à partir de ce moment: message d'erreur...
      }
      catch (...)
      {
        MessageBeep(0);
      }
      delete jp;            // liberer la memoire

  6. #6
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2011
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vaucluse (Provence Alpes Côte d'Azur)

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

    Informations forums :
    Inscription : Janvier 2011
    Messages : 19
    Par défaut
    petit up please

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 02/09/2014, 15h11
  2. Réponses: 4
    Dernier message: 29/10/2010, 14h40
  3. récupérer une image avec readfile
    Par julien1451 dans le forum Langage
    Réponses: 11
    Dernier message: 27/01/2010, 01h06
  4. Récupérer taille d'une image avec IE
    Par olbouss dans le forum jQuery
    Réponses: 5
    Dernier message: 03/11/2009, 09h20
  5. Réponses: 4
    Dernier message: 07/06/2006, 14h23

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