Probleme wsock protocole HTTP [Résolu]

Signaler
Messages postés
5
Date d'inscription
lundi 28 février 2005
Statut
Membre
Dernière intervention
6 juillet 2008
-
Messages postés
5
Date d'inscription
lundi 28 février 2005
Statut
Membre
Dernière intervention
6 juillet 2008
-
Alors je veux faire une petite appli qui permet de télécharger des fichiers sur le net suivant le protocole HTTP dont voici le code de la partie qui va chercher le fichier:

void getfile(SOCKET sock,SOCKADDR_IN sin,char* file){

FILE * infile;
infile = fopen(file,"wb");
char* mes = new char[255];
char* buffer = new char[1024];
int byteget;
bool header = false;
char* buf2;

connect(sock,(SOCKADDR *)&sin,sizeof(sin));

sprintf(mes,"GET /home/patcher/%s HTTP/1.0\r\nConnection: close\r\n\r\n",file);

send(sock,mes,strlen(mes),0);

while((byteget = recv(sock,buffer,1024,0)) > 0 ){
              
               if( !header ){
               buf2 = strstr(buffer,"\r\n\r\n") + 4;
               fwrite(buf2,byteget - (buf2-buffer),1,infile);
               header = true;
               }else{
                     fwrite(buffer,byteget,1,infile);
               }
}

shutdown(sock,2);
fclose(infile);

}

Je l'utilise dans une boucle dans laquelle je rentre un nom de fichier a télécharger, ça marche parfaitement la première fois (fichier complet sans soucis) mais si je lance un 2e téléchargement ensuite, celui-ci me donne un fichier vide... Merci de bien vouloir m'aider ^^

6 réponses

Messages postés
1905
Date d'inscription
mercredi 22 janvier 2003
Statut
Membre
Dernière intervention
17 septembre 2012
2
Salut,

j'ai bien compris a quoi servait le strstr(), mais comme son nom
l'indique c'est une fonction qui s'applique sur des chaines de
caracteres uniquement, pas sur des données brutes que tu recois avec
recv().

Pour le socket, il faut en recreer un nouveau pour chaque connexion (socket(), closesocket()).
Messages postés
482
Date d'inscription
vendredi 26 août 2005
Statut
Membre
Dernière intervention
5 décembre 2009

Bonjour,

Peut-être parce qu'il manque les delete qui doivent aller avec les new ?

Jean-François
Messages postés
5
Date d'inscription
lundi 28 février 2005
Statut
Membre
Dernière intervention
6 juillet 2008

Merci de ta réponse.

Non j'ai essayé a tout hasard, mais j'avais déjà commencé d'autres versions où  l'allocation de mémoire était faite avant itération (donc aucune necessité de delete entre chaque itération).

Je tiens aussi a préciser qu'en faisant des tests similaires avec le protocole FTP (en exécutant les instructions correctement) j'arrivais aussi a downloader un premier fichier mais pas un deuxième...

Ma question serait de savoir si une fois le socket fermé, il faut le réinitialiser d'une manière quelconques ou quoi? ...
Messages postés
1905
Date d'inscription
mercredi 22 janvier 2003
Statut
Membre
Dernière intervention
17 septembre 2012
2
Salut,
Commence surtout par traiter les erreurs des fonctions
winsock et d'afficher des messages en conséquence: ta fonction
n'affiche rien, ne log rien, ne retourne rien: a moins d'etre devin
c'est impossible a debuger. A mon avis, c'est le deuxieme connect() qui
échoue, je pense pas qu'on puisse réutiliser un socket de cette maniere
(même apres un shutdown).

Ensuite, y'a d'autres problemes, comme la fuite de mémoire signalée par
jfrancois, mais plus grave a mon avis, c'est le
"strstr(buffer,"\r\n\r\n")": le serveur n'envoie pas de chaine terminée
par 0, donc on peut pas utiliser strstr. Autre problême mineur, que se
passe-t-il lorsqu'on ne recoit qu'une partie de la réponse lors du
premier recv() ?
Messages postés
5
Date d'inscription
lundi 28 février 2005
Statut
Membre
Dernière intervention
6 juillet 2008

Merci pour ta réponse, il faudrait en effet que je soit un peu plus rigoureux lorsque je code et des récups d'erreurs ne font jamais de mal...

En ce qui concerne la fuite de mémoire, je l'ai réglé suite au message de jfrancois, en ce qui concerne le strstr il marche très bien (je comprend pas ce que tu veux dire par la), je l'utilise pour virer le header de la réponse du serveur HTTP au niveau des recv il gère tres bien les réponse au dela de la taille du buffer (j'ai envoyé au travers un fichier de 1Mo dont j'ai verifié le checksum), la boucle sert à ça...

Sinon lorsque je mes un récup d'erreur à la deuxieme tentative il me sort un code d'erreur 10056 >> Socket is already connected.

Que faudrait-il que je fasse? passer par des pointeurs et effacer les socket a la fermeture?
Messages postés
5
Date d'inscription
lundi 28 février 2005
Statut
Membre
Dernière intervention
6 juillet 2008

Merci beaucoup, ça marche maintenant...

Pour ce qui est  de la question du strstr, il est necessaire que ce soit une chaine uniquement car c'est le caractère \0 qui arrête la recherche non? dans mon cas j'ai choisi plutôt que de bidouiller avec des memcmp et memchr de rajouter un caractère \0 a la fin de la chaine et de faire coller le recv de façon à ce qu'il n'écrive pas par dessus ce dernier caractère, ce qui donne avec toutes les modifs:

void getfile(SOCKADDR_IN sin,char* file){
char* mes = new char[255];
char* buffer = new char[1025];
buffer[1024] = '\0';
int byteget;
bool header = false;
char* buf2;

SOCKET sock;

sock = socket(AF_INET,SOCK_STREAM,0);

if(connect(sock,(SOCKADDR *)&sin,sizeof(sin))==SOCKET_ERROR){
         Affsockerror();
}else{         
FILE * infile;
infile = fopen(file,"wb");

sprintf(mes,"GET /home/patcher/%s HTTP/1.0\r\nConnection: close\r\n\r\n",file);

send(sock,mes,strlen(mes),0);

while((byteget = recv(sock,buffer,1024,0)) > 0 ){
               
               if( !header ){
               buf2 = strstr(buffer,"\r\n\r\n") + 4;
               fwrite(buf2,byteget - (buf2-buffer),1,infile);
               header = true;
               }else{
                     fwrite(buffer,byteget,1,infile);
               }
}
closesocket(sock);
fclose(infile);
}
delete(mes);
delete(buffer);
}

Merci encore pour votre aide a tous les deux ^^