client http simple

Le
jean dupont
Bonjour,

Je souhaite créer un programme capable de lire une page sur un serveur http.
Voici le programme que j'ai écris, appelons le client.cpp:

#include <stdio.h>
#include <winsock.h>
#include <string.h>


void main(int argc,char **argv)
{
sockaddr_in sin;
WSADATA wsadata;
hostent *hp;
int err,unit;
char buffer[1500];
char *requete="GET / HTTP/1.0";

if(argc!=2) return;
err=WSAStartup(0x101,&wsadata);
if (err) {printf("erreur WSAStartup %d",err);}
else
{
hp = gethostbyname(argv[1]);
if (hp==NULL) {printf("erreur gethost %d",WSAGetLastError());}
else {
memset(&sin,0, sizeof(sin));
sin.sin_family_INET;
sin.sin_addr.s_addr=*(int*)(hp->h_addr);
sin.sin_port=htons(80);
if ((unit=socket(AF_INET,SOCK_STREAM,0)) < 0) {printf("erreur
socket");return;}
if (connect(unit,&sin,16)) {printf("erreur connect
%d",WSAGetLastError());return;}

printf("octets envoye: %d",send(unit,requete,strlen(requete),0));
printf("octets recus: %d",recv(unit,buffer,1500,0));

printf("%s",buffer);
}
}
WSACleanup();
}

En executant le programme, par exemple : client www.google.fr
le programme affiche octets envoye:16 octets recus:0
ce qui prouve que la requete a bien été envoyé mais que la réponse n'est pas
arrivée.
Quel est le problème?
Vos réponses
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Cyrille Szymanski
Le #9848511
Miam une revue de code.

On 2004-05-04, jean dupont
void main(int argc,char **argv)
{
sockaddr_in sin;



"struct sockaddr_in" ou "SOCKADDR_IN" pour être correct. Il semble
que le compilateur est C++ (vu qu'il laisse passer ça) mais ici je lis
du C.


WSADATA wsadata;
hostent *hp;
int err,unit;
char buffer[1500];



Mettez plutôt sin, *hp et uint plus bas pour ne pas occuper
inutilement l'espace des noms. Il me semble que unit devrait être un
SOCKET.


char *requete="GET / HTTP/1.0rn";



mieux : "GET / HTTP/1.0rnrn"
encore mieux : "GET / HTTP/1.1rnHost: www.google.frrnrn"


if(argc!=2) return;
err=WSAStartup(0x101,&wsadata);
if (err) {printf("erreur WSAStartup %dn",err);}
else
{
hp = gethostbyname(argv[1]);
if (hp==NULL) {printf("erreur gethost %dn",WSAGetLastError());}
else {
memset(&sin,0, sizeof(sin));



Ou SOCKADDR_IN sin = { 0 };

sin.sin_family¯_INET;
sin.sin_addr.s_addr=*(int*)(hp->h_addr);



Ici vous choisissez arbitrairement le premier s_addr du hostent.
Idéalement il faut itérer à travers ceux renvoyés tant que la
connexion échoue.


sin.sin_port=htons(80);
if ((unit=socket(AF_INET,SOCK_STREAM,0)) < 0) {printf("erreur



ici d'après le contexte on préfère utiliser PF_INET à AF_INET.

socketn");return;}



Un return qui n'a pas appelé WSACleanup();

if (connect(unit,&sin,16)) {printf("erreur connect



Mettre sizeof(sin) plutôt que 16.

%dn",WSAGetLastError());return;}



Un autre return sans WSACleanup();


printf("octets envoye: %dn",send(unit,requete,strlen(requete),0));



Oui mais non. Un appel à send ne garantit pas que toutes les données
seront envoyées. Il faut faire une boucle.

printf("octets recus: %dn",recv(unit,buffer,1500,0));



Idem, un appel à recv() ne garantit pas que toutes les données reçues
le soient en un appel.


printf("%s",buffer);



buffer n'est pas une chaîne ASCIIZ ce qui peut poser problème ici. Au
moins mettre buffer[1499]=NULL;

}
}
WSACleanup();
}




Quel est le problème?



Il serait très utile de lire la RFC sur le protocole HTTP.

--
cns
jean dupont
Le #9848131
"Cyrille Szymanski" 4097c1c5$0$13084$
Miam une revue de code.


> char *requete="GET / HTTP/1.0rn";

mieux : "GET / HTTP/1.0rnrn"
encore mieux : "GET / HTTP/1.1rnHost: www.google.frrnrn"



Avec cette modification ça marche!
Merci pour ton conseil.
Cyrille Szymanski
Le #9848091
On 2004-05-05, jean dupont
encore mieux : "GET / HTTP/1.1rnHost: www.google.frrnrn"



Avec cette modification ça marche!
Merci pour ton conseil.



Oui mais jette un oeil à la RFC quand même.

Je ne veux pas faire de présomptions éronées mais cela m'embêterait
que tu reviennes dans peu de temps avec une question du genre "je ne
sais pas pourquoi j'obtiens parfois des données éronnées, il
semblerait que le serveur envoie des lignes contenant un petit code du
type 'e8'".....

--
cns
Publicité
Poster une réponse
Anonyme