logo Homepage
Pages: [1]
  Imprimer  
Auteur Fil de discussion: [C] Impossibilité d'effectuer 2 requêtes HTTP successives avec le même socket  (Lu 14928 fois)
bentuximos
Profil challenge

Classement : 4337/54285

Néophyte
*
Hors ligne Hors ligne
Messages: 12


Voir le profil
« le: 30 Octobre 2008 à 12:29:03 »

Bonjour
Mon problème est peu être tout bête mais je n'arrive pas a trouver la solution.

J'ai réussi à faire les premières épreuves de programmation (renvoi) en python et j'ai donc décidé de faire les suivantes en C à l'aide des sockets.
Mon problème vient du fait que je n'arrive pas à exécuter la deuxième requête qui renvoie le résultat trouvé.
je m'explique :
      Dans mon code j'ouvre un socket puis j'effectue une premier requête HTTP GET et j'obtiens bien la page que je demande (ie : epreuves/prog/prog4.php )
      je traite les données reçus puis je refait une requête HTTP en incluant ma réponse mais je ne reçoit pas la bonne page, a la place je reçoit le code de la page d'accueil du site sans header http
      De plus j'ai essayer d'exécuter 2 fois la même requête sans succès, en faisant attention de bien spécifier Connection :Keep-Alive dans le header que j'envoie.

Le seul moyen que j'ai trouver pour que ça marche c'est de fermer le socket après la premier requête, puis d'en ouvrir un nouveau et d'effectuer la seconde.
Je cherche désespérément un moyen de faire les 2 requêtes avec le même socket
merci  de votre aide.


Voici le code que je tente de faire marcher :

Edit : J'ai retirer les sources pour ne pas donner de solution.



Si jamais je suis dans le mauvais topic  merci de me le signaler.
« Dernière édition: 17 Novembre 2008 à 14:11:14 par the lsd » Journalisée

« L'informatique n'est pas une science exacte, on n'est jamais à l'abri d'un succès. » Murphy
simpsonmaniac

Profil challenge

Classement : 567/54285

Membre Junior
**
Hors ligne Hors ligne
Messages: 60

Essayer, c'est le meilleur moyen de se planter...


Voir le profil
« #1 le: 30 Octobre 2008 à 15:39:16 »

Il y a un topic d'aide pour toutes les épreuves : http://www.newbiecontest.org/forums/index.php?topic=18.0
« Dernière édition: 30 Octobre 2008 à 16:12:37 par simpsonmaniac » Journalisée

C:/dos
C:/dos/run
run/dos/run
bentuximos
Profil challenge

Classement : 4337/54285

Néophyte
*
Hors ligne Hors ligne
Messages: 12


Voir le profil
« #2 le: 30 Octobre 2008 à 16:03:20 »

Dls je ne cherche pas à avoir la solution pour résoudre l'épreuve, j'ai pris ce topic car je cherche juste de l'aide et je pense que mon problème est très ciblé.
Je veux juste savoir pourquoi je ne peux pas effectuer la 2de requête?
Peut être faudrait il le mettre dans les afterwards ?


Journalisée

« L'informatique n'est pas une science exacte, on n'est jamais à l'abri d'un succès. » Murphy
simpsonmaniac

Profil challenge

Classement : 567/54285

Membre Junior
**
Hors ligne Hors ligne
Messages: 60

Essayer, c'est le meilleur moyen de se planter...


Voir le profil
« #3 le: 30 Octobre 2008 à 16:16:47 »

Peut être faudrait il le mettre dans les afterwards ?
Pas si tu n'as pas validé l'epreuve, c'est d'ailleurs l'intéret
« Dernière édition: 30 Octobre 2008 à 16:20:40 par simpsonmaniac » Journalisée

C:/dos
C:/dos/run
run/dos/run
bentuximos
Profil challenge

Classement : 4337/54285

Néophyte
*
Hors ligne Hors ligne
Messages: 12


Voir le profil
« #4 le: 30 Octobre 2008 à 16:23:40 »

OK je valide l'épreuve si c ça qui pose problème
Journalisée

« L'informatique n'est pas une science exacte, on n'est jamais à l'abri d'un succès. » Murphy
_o_
Relecteur

Profil challenge

Classement : 42/54285

Membre Héroïque
*
Hors ligne Hors ligne
Messages: 1258


Voir le profil
« #5 le: 30 Octobre 2008 à 16:28:51 »

Soyons sérieux, le code ne donnait aucune indication sur les épreuves de prog. De toute façon, faut être maso pour se retaper des sockets pour chaque épreuve de prog. Et si tu colles ton truc en afterwards, tu auras moins de public, ce qui ne t'aidera pas non plus.

Non, la bonne solution, c'est de rendre ton code générique et de faire disparaitre tout référence aux épreuves de nc, au cas où. Par exemple, arrange-toi juste pour qu'il récupère... je sais pas, la page d'accueil de google par exemple ? Sans cookie, sans rien de spécial, histoire de bien mettre en évidence ton problème et de réduire les possibilités.

Je pense qu'une fois ton problème réglé pour google, ça coulera de source pour NC.
Journalisée

Les épreuves de hack de NC sont trop faciles ? Et pourtant ! Bienvenue dans la vraie vie : http://thedailywtf.com/Articles/So-You-Hacked-Our-Site!.aspx
bentuximos
Profil challenge

Classement : 4337/54285

Néophyte
*
Hors ligne Hors ligne
Messages: 12


Voir le profil
« #6 le: 30 Octobre 2008 à 17:04:35 »

Voilà je rajoute mon code
Cette fois ci je veux obtenir la page de google.
j'ai ce que je demande à la première requête mais pas à la seconde

Code:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>

#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define closesocket(param) close(param)

typedef int SOCKET;
typedef struct sockaddr_in SOCKADDR_IN;
typedef struct sockaddr SOCKADDR;


char requete1[]="GET / HTTP/1.1\r\nHost: www.google.fr\r\nConnection:Keep-Alive\r\n\r\n";
char ch[2024];

int main()
{
SOCKET sock;
int ret = 0;
host = gethostbyname("www.google.fr");

sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == 0) printf("erreur ouverture socket"),exit(EXIT_FAILURE);
SOCKADDR_IN sin;
sin.sin_addr.s_addr = inet_addr(inet_ntoa( * (struct in_addr *)( host->h_addr_list[0]) ));
sin.sin_family = AF_INET;
sin.sin_port = htons(80);

ret = connect(sock, (SOCKADDR *)&sin, sizeof(sin) );
if (ret==0)
{
printf("Début de la Connexion au serveur \n");
send(sock,requete1,sizeof(requete1),0);
recv(sock,ch,sizeof(ch),0);

printf("Info recu :%s\n",ch);
memset(ch,0,sizeof(ch));

send(sock,requete1,sizeof(requete1),0);
recv(sock,ch,sizeof(ch),0);
printf("\n\nReponce recu :%s\n",ch);
}

closesocket(sock);
printf("Fin de la connexion au serveur\n");
return EXIT_SUCCESS;
}
Pouvez vous m'indiquer ce qui cloche merci
« Dernière édition: 31 Octobre 2008 à 11:08:50 par bentuximos » Journalisée

« L'informatique n'est pas une science exacte, on n'est jamais à l'abri d'un succès. » Murphy
_o_
Relecteur

Profil challenge

Classement : 42/54285

Membre Héroïque
*
Hors ligne Hors ligne
Messages: 1258


Voir le profil
« #7 le: 30 Octobre 2008 à 19:00:12 »

Cette fois ci je veux obtenir la page de google.

Tu as testé avant ? Parce que là, tu utilises encore l'IP de NC (man gethostbyname pour la prochaine fois).

j'ai ce que je demande à la première requête mais pas à la seconde

Si, si, tout est logique dans le fonctionnement. Je te remercie de cet exemple, qui va me permettre de marteler une chose importante dans la programmation en C et que je n'ai pas l'occasion d'exprimer souvent : on doit tester systématiquement les codes retours des fonctions que l'on appelle.

En l'occurrence, send et recv ont des codes retours, et il faut les tester. Exemple avec le man de recv :
Code:
Ces  trois routines renvoient la longueur du message si elles réussissent. Si un message est 
trop long pour tenir dans le tampon, les octets supplémentaires peuvent  être  abandonnés 
suivant  le  type  de socket utilisé.

Normalement, ça devrait te donner la puce à l'oreille sur quelque chose qui te manque. Mais tu devrais avoir compris rien qu'en lisant attentivement la sorte standard de ton programme et en comparant avec la page que te fournit ton navigateur.
Journalisée

Les épreuves de hack de NC sont trop faciles ? Et pourtant ! Bienvenue dans la vraie vie : http://thedailywtf.com/Articles/So-You-Hacked-Our-Site!.aspx
bentuximos
Profil challenge

Classement : 4337/54285

Néophyte
*
Hors ligne Hors ligne
Messages: 12


Voir le profil
« #8 le: 31 Octobre 2008 à 11:07:14 »

Merci beaucoup pour ces explications
Effectivement je n'avais pas fait attention au faite que les données sont "présentes dans la connexion" tend qu'elles n'ont pas été toutes reçues grâce à la fonction recv.
En plus il existe une limite dans la taille des données que l'on peut recevoir donc quelque soit la taille du buffer on ne reçoit pas tout, ce qui explique pourquoi j'avais la suite du code de la page avec un second appel à recv.
Et pour finir le tout était couplé à un dépassement de buffer, car comme la réception était incomplète je n'avais pas forcement le caractère de fin de chaîne '\0' ce qui affichait n'importe quoi.

Par contre je n'ai pas trouvé comment ignorer les caractères qui ne rentrent pas dans le buffer lors de la réception et donc éviter de devoir tout recevoir
D'aprés le man de recv (si j'ai bien compris ) il faut changer de type de socket mais je n'ai pas compris comment ?
Journalisée

« L'informatique n'est pas une science exacte, on n'est jamais à l'abri d'un succès. » Murphy
_o_
Relecteur

Profil challenge

Classement : 42/54285

Membre Héroïque
*
Hors ligne Hors ligne
Messages: 1258


Voir le profil
« #9 le: 31 Octobre 2008 à 11:43:43 »

Tu as tout compris.

Par contre je n'ai pas trouvé comment ignorer les caractères qui ne rentrent pas dans le buffer lors de la réception et donc éviter de devoir tout recevoir

Ouais. Heu... Je ne vois pas bien l'intérêt. Quand on fait appel à un service réseau, c'est pas pour ignorer sa réponse. Si le but est d'ignorer une partie, le mieux est de tout recevoir, de parser et de ne garder que ce qui t'intéresse.

Citation
D'aprés le man de recv (si j'ai bien compris ) il faut changer de type de socket mais je n'ai pas compris comment ?

Le type de stocket, tu le définis lors de l'appel à la fonction socket (ici SOCK_STREAM). Cela dit, ce type est défini aussi par le protocole que tu utilises. En l'occurrence, HTTP, c'est TCP, donc y'a pas 36 types de sockets possibles. Peut-être en raw ? Bref, dans ton cas, je ne vois pas l'intérêt.
Journalisée

Les épreuves de hack de NC sont trop faciles ? Et pourtant ! Bienvenue dans la vraie vie : http://thedailywtf.com/Articles/So-You-Hacked-Our-Site!.aspx
bentuximos
Profil challenge

Classement : 4337/54285

Néophyte
*
Hors ligne Hors ligne
Messages: 12


Voir le profil
« #10 le: 31 Octobre 2008 à 12:04:57 »

Citation
Par contre je n'ai pas trouvé comment ignorer les caractères qui ne rentrent pas dans le buffer lors de la réception et donc éviter de devoir tout recevoir
J'ai ecrit ça par rapport au contenu du man

Code:
Ces  trois routines renvoient la longueur du message si elles réussissent. Si un message est 
trop long pour tenir dans le tampon, les octets supplémentaires peuvent  être  abandonnés 
suivant  le  type  de socket utilisé.
Mais si ça n'a pas vraiment d'intérêt c'est tout aussi bien de tout recevoir, puis de trier.

Très bien merci beaucoup pour votre aide,maintenant je sais qu'il ne faut surtout pas délaisser les retours de fonction ce qui m'évitera de faire ce genre d'erreur.


Journalisée

« L'informatique n'est pas une science exacte, on n'est jamais à l'abri d'un succès. » Murphy
alph1

Profil challenge

Classement : 54/54285

Membre Complet
***
Hors ligne Hors ligne
Messages: 178


Voir le profil
« #11 le: 31 Octobre 2008 à 12:13:15 »

Tu devrais implémenter une boucle afin de tout recevoir.
D'autre part il me semble qu'il te manque un "#include <string.h>" (pour le memset) : étrange que ton compilateur ne dise rien.
Journalisée

Physics is like sex. Sure, it may give some practical results, but that's not why we do it. (Richard P. Feynman)
_o_
Relecteur

Profil challenge

Classement : 42/54285

Membre Héroïque
*
Hors ligne Hors ligne
Messages: 1258


Voir le profil
« #12 le: 31 Octobre 2008 à 13:31:03 »

D'autre part il me semble qu'il te manque un "#include <string.h>" (pour le memset) : étrange que ton compilateur ne dise rien.

Avec gcc, c'est juste un avertissement.
Journalisée

Les épreuves de hack de NC sont trop faciles ? Et pourtant ! Bienvenue dans la vraie vie : http://thedailywtf.com/Articles/So-You-Hacked-Our-Site!.aspx
bentuximos
Profil challenge

Classement : 4337/54285

Néophyte
*
Hors ligne Hors ligne
Messages: 12


Voir le profil
« #13 le: 01 Novembre 2008 à 09:55:58 »

Après avoir corrigé mon code je l'ai essayé sur un site en local et il a très bien fonctionné (la 2de requête me renvoie bien ce que je demande).
Mais lorsque je l'utilise sur google par exemple la 2de requête sensée demander GET /firefox me renvoie le code de la page d'accueil du cite sans header.
Je n'arrive pas à savoir pourquoi et le plus bizarre c'est que cela marche très bien en utilisant les socket en python.
Il y a t'il un mécanisme de protection concernant le temps minimal entre 2 requêtes ou quelque chose du même genre ?
« Dernière édition: 01 Novembre 2008 à 10:02:40 par bentuximos » Journalisée

« L'informatique n'est pas une science exacte, on n'est jamais à l'abri d'un succès. » Murphy
Pages: [1]
  Imprimer  
 
Aller à: