Journal petite question sur les transfert dans le protocole http

Posté par  .
Étiquettes : aucune
0
7
avr.
2003
Voila pour un serveur d'une application client/serveur, je suis en train de faire une interface web pour l'administration du serveur. Sortie de micro micro void même nano serveur web ultra spécialisé, mais pour que cela soit joli je veux qu'il envoie de l'image en plus du texte.
D'où ma question de quel façon est envoyé une image au brower lorsque celui faire une requte get sur l'image (pas l'identication de la demande de l'image mais le transfert lui-même)?
  • # Re: petite question sur les transfert dans le protocole http

    Posté par  (site web personnel) . Évalué à 2.

    $ telnet linuxfr.org 80
    Trying 212.27.33.221...
    Connected to prout.linuxfr.org (212.27.33.221).
    Escape character is '^]'.
    GET /images/en.png HTTP/1.1
    Host: linuxfr.org

    HTTP/1.1 200 OK
    Date: Mon, 07 Apr 2003 09:04:08 GMT
    Server: Apache/1.3.26 (Unix) Debian GNU/Linux mod_gzip/1.3.19.1a PHP/4.1.2 mod_ssl/2.8.9 OpenSSL/0.9.6g
    Last-Modified: Wed, 27 Mar 2002 17:38:35 GMT
    ETag: "cef99-297-3ca2039b"
    Accept-Ranges: bytes
    Content-Length: 663
    Content-Type: image/png

    Contenu du fichier image
    • [^] # Re: petite question sur les transfert dans le protocole http

      Posté par  . Évalué à 2.

      J'ai essayé ca marche pas:
      alors deux choses:
      -est-ce que ETag est obligatoire et a quoi ca correspond?
      -Apparement le contenu n'est pas envoyé en entier (j'ouvre le fichier comme un fichier texte et j'envoie son contenu comme chaîne de caractère c bon ou pas?
      • [^] # Re: petite question sur les transfert dans le protocole http

        Posté par  . Évalué à 1.

        j'ouvre le fichier comme un fichier texte et j'envoie son contenu comme chaîne de caractère c bon ou pas?

        Hmmm, le probleme peu venir de là. Si la fonction utilisée pour écrire le fichier sur la socket est du type *printf, ça va foirer : pour printf, un caractere nul (\0) dans la chaine indique la fin de la chaine. Il est fort possible que ton image contienne le caractere nul. Utilise plutôt la fonction write(int file_desc, void * datas, int length).
        • [^] # Re: petite question sur les transfert dans le protocole http

          Posté par  . Évalué à 1.

          pour le développement j'utilise Qt, donc la récupération du contenu s'effectue avec QTextStream sur le fichier et stocké dans un QString. L'envoye au serveur s'effectue lui par le biais d'un QSocket.
          • [^] # Re: petite question sur les transfert dans le protocole http

            Posté par  . Évalué à 1.

            Evite tout ce qui est *TextStream ...
            Prefere un truc du genre *BinaryStream ...

            La raison est que certains caracteres sont interpretes a la volee ...
            Le \b, le \0 et d'autres caracteres ...

            Lorsque tu lis un fichier binaire, fais toujours gaffe a ne jamais interpreter ce que tu lis : utilise un flux de lecture binaire ...

            La doc QT suggere d'utiliser les readBlock sur QIODevice ...
            Par l'intermediaire d'un QFile pour ce qui est de lire le fichier ...

            Pour l'envoi sur la socket, QSocket est un QIODevice aussi, utilise la methode writeBlock ...
            • [^] # Re: petite question sur les transfert dans le protocole http

              Posté par  . Évalué à 1.

              j'ai bien essayé mais au mieux je n'ai que 13 bytes de l'image envoyé ce qui est pire que ce que je faisais avant, au pire j'ai un segfmentation fault: voici min code au cas où:
              const QFileInfoList *fil=actuPath->entryInfoList(fn);
              QFileInfoListIterator it(*fil);
              QFileInfo *fi=it.toFirst();
              QString imgformat=fn.mid(fn.findRev(".")+1);
              QFile iod(fi->filePath());
              if(iod.open(IO_ReadOnly))
              {
              char *fir;
              uint ui=(uint)iod.size();
              iod.readBlock(fir,ui);
              const char* cc=(const char*)fir;
              qcs=(QCString)cc;
              QTextStream ts(s);
              QString imgstr=QString("Content-type: image/%1\n\r").arg(imgformat)+QString("Content-length: %1\n\r").arg(qcs.length())+QString("Accept-Ranges: bytes\n\n");//.arg(fir);
              ts<<imgstr;
              ts.unsetDevice();
              s->writeBlock(qcs,qcs.length());
              //cc=imgstr.local8Bit()+cc;
              iod.close();
              s->close();
              }
              • [^] # Re: petite question sur les transfert dans le protocole http

                Posté par  . Évalué à 6.

                > qcs=(QCString)cc; Chaine de caractère. qcs prend en compte cc jusqu'au premier '\0' rencontré (bonne probabilité de plantage). Puisque ni fir et ni cc n'est une chaine de caractère, ne les type pas en (char*). Utilise void * . > QString("Content-length: %1\n\r").arg(qcs.length()) qcs.length te donne la longueur d'une chaine de caractère. Donc dès que le premier caractère '\0' est rencontré. > s->writeBlock(qcs,qcs.length()); Même erreur. QString n'est pas adapté. Pour un bout de code de 20 ligne, utiliser qcs est un peu "ridicule". Un truc du style : struct { void * data ; size_t size ; // pas int. C'est pas un nombre c'est une taille ! } img ; img.size=(uint)iod.size(); iod.readBlock(img.date,img.size); QTextStream ts(s); QString imgstr=QString("Content-type: image/%1\n\r").arg(imgformat)+QString("Content-length: %1\n\r").arg(img.size)+QString("Accept-Ranges: bytes\n\n"); ts<<imgstr; ts.unsetDevice(); s->writeBlock(img.data, img.size); iod.close(); s->close(); } NB : j'y connais rien en qt.
                • [^] # Re: petite question sur les transfert dans le protocole http

                  Posté par  . Évalué à 1.

                  j'ai essayé au cas où car pas con Pb: que ce soit iod ou s qui sont descendant de QIODevice, ne supporte pas de void* dans les fonctions writeBlock ou readBlock, si j'essaye il me refoule et je me trouve donc devant le problème de typage -n'accepte que char*,uint ou QByteArray- Merci qd même
                  • [^] # Re: petite question sur les transfert dans le protocole http

                    Posté par  . Évalué à 7.

                    > que ce soit iod ou s qui sont descendant de QIODevice, ne supporte pas de void* dans les fonctions writeBlock ou readBlock, Le language C avec la libc conserve toujours un certain charme :-) ... fais un man write, open, read, malloc, realloc, free et tu auras un réponse évidente à ton problème. Faut pas faire de l'objet pour faire de l'objet. Vois aussi que readBlock attent un (char *) et non un (char **). Donc la fonction ne fait pas de malloc ! Danger ! Si la fonction attend un (char *), elle a tord. Désolé. C'est de la programmation des années 70. Face à ça, faire un cast de (void *) à (char *) n'est pas dramatique. Il n'y a pas de conversion, c'est pour virer un warning du compilo. voilà le proto de read() qui est posix : ssize_t read(int fd, void *buf, size_t count); (void *) pour les data. (size_t) pour la taille. Tu peux te permètres un cast. #include <stdio.h> struct { void * data ; size_t size ; // pas int. C'est pas un nombre c'est une taille ! } img ; img.size= iod.size(); if ((img.data=malloc(img.size)) == NULL) { perror(NULL) ; exit(EXIT_FAILURE) } iod.readBlock((char *)img.data,img.size); QTextStream ts(s); QString imgstr=QString("Content-type: image/%1\n\r").arg(imgformat)+QString("Content-length: %1\n\r").arg(img.size)+QString("Accept-Ranges: bytes\n\n"); ts<<imgstr; ts.unsetDevice(); s->writeBlock((char *)img.data, img.size); iod.close(); s->close(); free(img.data); }
                • [^] # Re: petite question sur les transfert dans le protocole http

                  Posté par  . Évalué à 7.

                  > size_t size ; // pas int. C'est pas un nombre c'est une taille ! Ok, tu utilise uint qui est utilisé partout dans qt. Mais sur alpha par exemple : sizeof(void*) = 8 sizeof(int) = 4 size_t est généralement plus adapté (c'est le type retourné par strlen() par exemple). Mais il est vrai que beaucoup de librairies utilisent un int pour les tailles.
                • [^] # Re: petite question sur les transfert dans le protocole http

                  Posté par  . Évalué à 1.

                  On va se repeter : eviter tout ce qui est du style *String* ou certains caracteres sont interpretes ... Ensuite : char *fir; uint ui=(uint)iod.size(); iod.readBlock(fir,ui); Tu n'as pas alloue ton 'fir' ... T'as pas peur toi ... qcs=(QCString)cc; T'utilises un cast, alors que tu n'as pas construit l'objet ... T'as pas peur toi ... QTextStream ts(s); On avait dit, pas de *TextStream, pas de *String* ... Le reste est du meme acabit ... Essaye un truc simple : #define CHUNK_SIZE 100 QFile file(); // pseudo code, je te laisse le soin de l'initialiser QSocket socket(); // pareil char data[CHUNK_SIZE]; while (!file.atEnd()) { Q_LONG read = file.readBlock(data, CHUNK_SIZE); Q_LONG written = socket.writeBlock(data, read); if (written == -1) { // an error occurred } }
      • [^] # Re: petite question sur les transfert dans le protocole http

        Posté par  . Évalué à 1.

        j'ai eu des probleme une fois aussi en PHP pour communiquer en HTTP
        a cause des fin de ligne qui doivent etre "\r\n" et non "\n"

        p.e. une piste ....
  • # Re: petite question sur les transfert dans le protocole http

    Posté par  . Évalué à 6.

    J'ai rien compris.
    ****************************************************
    $ get -d http://linuxfr.org/images/top_bar_left_logo.png(...)
    DEBUG output created by Wget 1.8.2 on linux-gnu.

    --11:06:18-- http://linuxfr.org/images/top_bar_left_logo.png(...)
    => `top_bar_left_logo.png'
    Résolution de linuxfr.org... complété.
    Caching linuxfr.org => 212.27.33.221
    Connexion vers linuxfr.org[212.27.33.221]:80...connecté.
    Created socket 3.
    Releasing 0x8098390 (new refcount 1).
    ---request begin---
    GET /images/top_bar_left_logo.png HTTP/1.0
    User-Agent: Wget/1.8.2
    Host: linuxfr.org
    Accept: */*
    Connection: Keep-Alive

    ---request end---
    requête HTTP transmise, en attente de la réponse...HTTP/1.1 200 OK
    Date: Mon, 07 Apr 2003 09:05:39 GMT
    Server: Apache/1.3.26 (Unix) Debian GNU/Linux mod_gzip/1.3.19.1a PHP/4.1.2 mod_ssl/2.8.9 OpenSSL/0.9.6g
    Last-Modified: Thu, 20 Feb 2003 16:20:31 GMT
    ETag: "8f5-d759-3e55004f"
    Accept-Ranges: bytes
    Content-Length: 55129
    Keep-Alive: timeout=15, max=512
    Connection: Keep-Alive
    Content-Type: image/png


    Found linuxfr.org in host_name_addresses_map (0x8098390)
    Registered fd 3 for persistent reuse.
    Longueur: 55,129 [image/png]

    100%[=========================================================================================================================================================>] 55,129 11.48K/s ETA 00:00

    11:06:26 (11.48 KB/s) - « top_bar_left_logo.png » sauvegardé [55129/55129]
    ****************************************************

    C'est comme une page http mais il faut que l'entête indique une image (C'est le "Content-Type: image/png"). Avec php la fonction header() peut générer l'entête :
    http://www.php.net/manual/fr/function.header.php(...)
    Le contenu, dans ce cas, peut venir d'une base de donnée ou autre. C'est php qui fait tout le boulot et non apache. Tu peux aussi utiliser gd pour générer l'image à la volé :
    http://www.boutell.com/gd/(...)

    Mais si l'image est un fichier "normal", le serveur apache fait tout lui-même.
  • # Re: petite question sur les transfert dans le protocole http

    Posté par  . Évalué à 1.

    BAHHHHHH!!!!!!!!!!!!!!!!!!!!!!!!
    Merci mon gars, ca fait je ssais plus combien de temps que je pagouille avec ces histoires de \0 dans les fichiers images! Je suis pas un super pro des sockets et du C, et le coup des pointeur void , je m'u attendais pas...
    Resuktat, j'ai tous les fichiers qui passe, je vais enfin pouvoir aller me coucher.........

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.