Envoyer un fichier binaire dans une socket

Signaler
Messages postés
137
Date d'inscription
lundi 13 décembre 2004
Statut
Membre
Dernière intervention
16 juillet 2007
-
Messages postés
137
Date d'inscription
lundi 13 décembre 2004
Statut
Membre
Dernière intervention
16 juillet 2007
-
salut a tous,
j'ai posté un précédent message sur un sujet similaire mais j'ai pas eu d'explication comprehensible.
voila je suis en train de realiser un serveur http et j'arrive pas a transmettre tout ce qui est binaire au navigateur.
pour les fichiers texte(html, txt ...) aucun pb: j'utilise les fonction createfile, readfile et closehandle de winsock2 pour recuperer le contenu du fichier, le mettre dans un buffer et transferer le contenu au navigateur via une socket.
j'ai une boucle qui capte toutes les requetes du navigateur. lorsque j'envoie une page html vide avec juste une image en background, le navigateur m'envoie 2 requetes:
- la 1ere pour la page html
- la 2e pour l'image jpeg d'arriere plan.
pour la 2e requete, le navigateur reste bloqué sur en attente de la reponse. donc en gros mon navigateur ne lui envoie pas la photo en binaire.
donc voici ma question: comment ouvrir un fichier binaire (en lecture bien sur) et le transferer dans une socket au navigateur avec les fonctions createfile et readfile ? quels sont les flags a specifier ? si cela semble plus aisée avec une autre api, je suis aussi preneur.
merci de vos reponses

22 réponses

Messages postés
933
Date d'inscription
dimanche 1 avril 2001
Statut
Membre
Dernière intervention
9 janvier 2012
2
Comme normal : hfl = CreateFile("monfichier.jpg", GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0);

Et après ReadFile, ...

@+
Arnotic,
Admin CS,
Développeur chez Néos SDI,
MVP Visual C++
Messages postés
137
Date d'inscription
lundi 13 décembre 2004
Statut
Membre
Dernière intervention
16 juillet 2007
1
je te remercie de ton apport mais c'est deja ce que je faisais mais a la suite du CreateFile("monfichier.jpg", GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0), lorsque j'eesaie de recuper la taille du fichier pour la mettre dans l'entente HTTP Content-Length,
il me retroune -1 avec la fonction tailleFichier = GetFileSize(file,NULL);
et pourtant la page html il me retourne bien la bonne taille (1072 pour ma page de test).
donc si la taille est a -1, soit il n'arrive pas a ouvrir le jpeg, soit je ne specifie pas les bons flags. c'est pkoi reste en attente car il ne recoit pas la photo de mon serveur .... le buffer qui lui est envoyé est vide ...

GRRRRR je vais m'arracher les cheveux
j'ai deja une calvitie naissante

PLIZ HELP
Messages postés
2670
Date d'inscription
vendredi 25 janvier 2002
Statut
Membre
Dernière intervention
6 février 2013
2
Mets le bout de code qui ouvre le fichier et recupere la taille ici qu'on puisse t'aider.
Messages postés
933
Date d'inscription
dimanche 1 avril 2001
Statut
Membre
Dernière intervention
9 janvier 2012
2
Oui,
De plus pour vérifier l'ouverture du fichier il faut faire : if(hfl != INVALID_HANDLE_VALUE)
De cette manière tu pourras voir si ca vient de l'ouverture du fichier.

@+
Arnotic,
Admin CS,
Développeur chez Néos SDI,
MVP Visual C++
Messages postés
137
Date d'inscription
lundi 13 décembre 2004
Statut
Membre
Dernière intervention
16 juillet 2007
1
c'est vrai.
en verifiant le handle il est bien valide et je recupere a present la taille du fichier mais maintenant il envoie du binaire au navigateur.
voici ce qu'il envoie au navigateur: ÿØÿà
et voici un apercu du code:

file = CreateFile(url, GENERIC_READ, 0,0,OPEN_EXISTING, 0,0);
if(file == INVALID_HANDLE_VALUE)
MessageBox(NULL,"il n'ouvre rien du tout",NULL,MB_OK);
tailleFichier = GetFileSize(file,NULL);
octet = new char[tailleFichier+1];
reponse = new char[tailleFichier+1024];
ReadFile(file,octet,tailleFichier,&nbOctetsLus,NULL);
CloseHandle(file);
if(strcmp(typeFichier, "jpg")==0)
strcpy(reponse, "HTTP/1.0 200 OK\nContent-Type: image/jpeg\nContent-Encoding: gzip,deflate\n\n\n");
if((strcmp(typeFichier, "htm")==0)||(strcmp(typeFichier, "html")==0))
strcpy(reponse, "HTTP/1.0 200 OK\nServer: MonServeur 1.0\nContent-Type: text/html\n\n");

send(acceptSocket,reponse,tailleFichier+1024,0);
delete[] octet;
delete[] reponse;
delete[] requete;
delete[] url;
delete[] sschaine1;
delete[] sschaine2;
closesocket(acceptSocket);

tout ce code est contenu dans la boucle de reception des requetes
la variable taille fichier recoit bien 1072 pour la 1e requete et 167010 pour la seconde requete donc il ouvre bien le fichier jpeg.
mais il envoie des hieroglyphes au navigateur
Messages postés
933
Date d'inscription
dimanche 1 avril 2001
Statut
Membre
Dernière intervention
9 janvier 2012
2
Vérifie que ta fonction send fonctionne bien.
Car si tu envois trop de données d'un coup elle peut échouer.

@+
Arnotic,
Admin CS,
Développeur chez Néos SDI,
MVP Visual C++
Messages postés
137
Date d'inscription
lundi 13 décembre 2004
Statut
Membre
Dernière intervention
16 juillet 2007
1
le fichier jpeg contient en fait 163810 octets (getfilesize)et en recuperant la valeur de la fonction send par
int i = send(acceptSocket,reponse,tailleFichier+1024,0);
il m'affiche 164834 octets. donc il envoie bien le fichier et l'entete http.
je faisais avec firefox et c'est pareil avec IE. il affiche toujours des hieroglyphes
Messages postés
933
Date d'inscription
dimanche 1 avril 2001
Statut
Membre
Dernière intervention
9 janvier 2012
2
Dans le code que tu as posé, ou envois-tu "octect" qui contient les données du fichier ? Je ne vois qu'un send pour "reponse".

@+
Arnotic,
Admin CS,
Développeur chez Néos SDI,
MVP Visual C++
Messages postés
2670
Date d'inscription
vendredi 25 janvier 2002
Statut
Membre
Dernière intervention
6 février 2013
2
tailleFichier+1024 <<< T'es sure que ton entete fasse cette taille ? Normal que tu es des hieroglyphes, la socket de l'explorateur va lire trop loin dans le buffer de récéption. Il faut qur tu mettes la tailles exactes de ta requets, et non pas la taille du fichier + 1024. Puis d'ailleurs pourquoi 1024 ?

Le troisième parametre de la fonction send correspond a la tailles des données contenu dans le buffer, et non pas la taille du buffer!!!!

Tu dois donc lui passer la taille réelle de ta requetes et non pas la taille du buffer (taillefichier + 1024)!.

Soit:

send(acceptSocket,reponse,strlen(reponse),0);


Essaye dont...
Messages postés
933
Date d'inscription
dimanche 1 avril 2001
Statut
Membre
Dernière intervention
9 janvier 2012
2
strlen() ne fonctionnera pas forcement. ton fichier jpeg peut contenir des 0x00 et strlen s'arretera de compter.
il faut taillefichier+tailleentete

@+
Arnotic,
Admin CS,
Développeur chez Néos SDI,
MVP Visual C++
Messages postés
137
Date d'inscription
lundi 13 décembre 2004
Statut
Membre
Dernière intervention
16 juillet 2007
1
1024 au hasard pour la taille de l'entete http.
en utilisant strlen(reponse) send n'envoie que 80 et quelques d'octets.
mais en combinant taillefichier+tailleentete il envoie 163908, donc la taille exacte du fichier (163810) + la taille exacte de l'entete.
tout a l'heure il envoyait 164834.
mais ca fait exactement la meme chose.
pour arnotic: en fait je fais un strcat de octet dans reponse. c'est vrai que je ne l'ai pas mis dans le copier coller mais ca donne ca:
strcpy(reponse, "HTTP/1.0 200 OK\nContent-Type: image/jpeg\nContent-Encoding: gzip,deflate\n\n");
strcat(reponse, octet);
Messages postés
2670
Date d'inscription
vendredi 25 janvier 2002
Statut
Membre
Dernière intervention
6 février 2013
2
Arnotic> T'es sure d'avoir bien lu le code ?
Un peu de bon sens...
Regarde ce qu'il a fait dans son send, il envoie que l'entete, il convient donc d'envoyer la taille de l'entete et non pas la taille du fichier + 1024.

ebooserge> Essaye de faire comme je te l'ai dis et dis moi ce que ca donne.
Dans la lancé envoie moi aussi la RFC avec le numéro de la page ou ils traitent de l'envoie des images (shellkode at hotmail.com)
Messages postés
137
Date d'inscription
lundi 13 décembre 2004
Statut
Membre
Dernière intervention
16 juillet 2007
1
comme je le disais plus haut, en utilsant strlen(reponse), la fonction send n'envoie que quelques octets qui correspondent a l'entete.
mais lorsque je fais taillefichier+taille entete, il envoie la taille exacte des 2 elements, et non plus la taille totale du buffer comme il me le faisait avant.

pour ce qui est de la rfc elle demande juste de specifier l'entete image/jpeg dans content-type et d'inclure l'image dans le corps de la reponse. etant donné que c'est une norme d'utilisation pour différents langages, elle ne specifie pas comment envoyer le fichier binaire en c++

voici la version officielle qui m'a inspiré: http://www.ietf.org/rfc/rfc2616.txt
et par ici une version francaise qui aborde les grand points: http://abcdrfc.free.fr/rfc-vf/rfc1945.html

j'en peux plus je suis naze je suis a 2 doigts d'abandonner
Messages postés
2670
Date d'inscription
vendredi 25 janvier 2002
Statut
Membre
Dernière intervention
6 février 2013
2
Ce qui me parait bizarre dans ton code, c'est le fait que ton serveur doit envoyer lui meme l'image.
Il me paraitrait plus logique que se soit l'explorateur qui les récupere lui meme.

Pour preuve, quand tu ouvres une pages web, tout d'abord, tout le texte va s'afficher, ensuite a la fin les images von etre telechargées puis afficher une a une.
La preuve que cela se passe bien en dehors de l'entete.

Je vais jeter un oeil a la RFC au cas ou.

Abandonne pas, ca serait trop facile :-)
Messages postés
933
Date d'inscription
dimanche 1 avril 2001
Statut
Membre
Dernière intervention
9 janvier 2012
2
Bien sur que le browser demande l'image. Pour preuve de ce qu'envoi IE pour google.fr par exemple :

GET / HTTP/1.1
Accept: */*
Accept-Language: fr
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 2.0.50215)
Host: www.google.fr
Connection: Keep-Alive
Cookie: PREF=ID=e8cf68786ba99fca:LD=fr:TM=1119198304:LM=1119198304:S=ZYtUoG2oxis20Za6


$!GET /intl/fr_fr/images/logo.gif HTTP/1.1
Accept: */*
Referer: http://www.google.fr/
Accept-Language: fr
Accept-Encoding: gzip, deflate
If-Modified-Since: Mon, 25 Apr 2005 21:08:03 GMT
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 2.0.50215)
Host: www.google.fr
Connection: Keep-Alive
Cookie: PREF=ID=e8cf68786ba99fca:LD=fr:TM=1119198304:LM=1119198304:S=ZYtUoG2oxis20Za6

Et le serveur renvoi l'image, et une fois que IE la reçu l'affiche.

@+
Arnotic,
Admin CS,
Développeur chez Néos SDI,
MVP Visual C++
Messages postés
137
Date d'inscription
lundi 13 décembre 2004
Statut
Membre
Dernière intervention
16 juillet 2007
1
tout a fait car lorsque le navigateur demande une page html, il ne sait pas ce qu'il ya dedans.
le serveur lui non plus ne sait pas ce qu'il ya dedans.
c'est au navigateur d'analyser les balises html et s'il ya des images, il envoie une requete pour chaque image referencée (et non pas contenue) dans la page html.
en gros:
une page html simple avec que du texte => une seule requete du navigateur
une page avec du texte et un background image => 2 requetes du navigateurs.
donc il faut lui envoyer d'abord la page et ensuite s'il tedemande la photo pour le background, tu dois lui envoyer la photo qui se trouve dans le dossier de tes pages web en principe ou ailleurs sur ton pc.
l'explorateur n'y est strictement pour rien.
et puis je l'ai vérifié car avec la boucle de capture des requetes et la fonction recv, je recois d'abord la demande de la page(settings.html). je lui envoie la page, il commence a l'affiche et ensuite il m'envoie une 2e requete pour me demander la photo. et c'est la que ca coince.
Messages postés
2670
Date d'inscription
vendredi 25 janvier 2002
Statut
Membre
Dernière intervention
6 février 2013
2
Voila de quoi t'aider.

Va a cette adresse et telecharge les deux ZIP.*
Tu trouveras un exemple de serveur HTTP, ainsi que ces sources.
Il est en C/C++ :

http://shellkode.free.fr/http/

Lache pas l'affaire, je suis persuadé que c'est une erreur bidon que t'as fait.
Messages postés
137
Date d'inscription
lundi 13 décembre 2004
Statut
Membre
Dernière intervention
16 juillet 2007
1
je te remercie pour cette source ...
je suis en train de la decortiquer et je vous dirais si ca marche et les modifs qu'il fallait faire avant de cliquer sur reponse acceptée. ca pourra toujours aider quelqu'un d'autre
Messages postés
2670
Date d'inscription
vendredi 25 janvier 2002
Statut
Membre
Dernière intervention
6 février 2013
2
Yop,
Si t'as besoin d'aides pour la compréhension du code n'hésites pas.
J'y ai jeté un oeil mais ca a l'air de resté basique.
Tu risques plus d'avoir des problèmes de compréhension au niveau de la méthode employé par le gars que par les lignes de codes elles memes.

Si tu ne connais pas les thread se sera peut etre la seule difficulté.
Messages postés
137
Date d'inscription
lundi 13 décembre 2004
Statut
Membre
Dernière intervention
16 juillet 2007
1
pour les threads ca va ya pas de pb.
je faisais une pause donc j'ai pas encore regardé.
mais c'a m'a l'air un peu long.
je vois qu'il ouvre son fichier avec la fonction standard fopen et qu'il specifie les param "a+b" en ouverture, avec b pour binary.
ensuite la methode est ingenieuse pour recuperer la taille du fichier.
mais j'ai pas trouvé la section ou il fait l'envoi des données au navigateur. (le send)
si tu peux juste m'extraire cette petite partie car je la trouve pas.
pour le moment je fais l'interface graphique (je sais ca peut se faire en ligne de commande mais j'aime bien les interfaces graphiques )