IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Réseau : problème d'écoute


Sujet :

C++

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    57
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 57
    Points : 26
    Points
    26
    Par défaut Réseau : problème d'écoute
    Bonjour à tous !
    Voici mon problème : je crée un client web, qui envoie une requete http à un serveur et attend la réponse avec un recv();
    Mais il arrive fréquemment que la réponse arrive en plusieurs fragments, et que je doive faire plusieurs recv(); pour tout récupérer et avoir une requete correcte... Comment pallier ceci ?

  2. #2
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    Quelle bibliothèque ?

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    57
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 57
    Points : 26
    Points
    26
    Par défaut
    ben j'utilise winsock2
    est-ce que quelqu'un a une solution ?
    Je me disais qu'on pouvait peut-être récupérer les octets un par un pour détecter l'octet correspondant a la fin de la requete...

  4. #4
    Membre régulier Avatar de psyphi
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    119
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Allemagne

    Informations professionnelles :
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2006
    Messages : 119
    Points : 120
    Points
    120
    Par défaut
    Suffit de faire une boucle qui reçoit jusqu'a ce qu'on ne lui envoie plus rien
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    int bytesRecv = SOCKET_ERROR;
    do{
        bytesRecv = recv(socket, buffer, sizeof (buffer)-1, 0);
        if( bytesRecv == SOCKET_ERROR){
             cerr<<"Erreur socker"<<endl;
             break;
        }else
             response.append(buffer);
    }while(bytesRecv != 0);

  5. #5
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    57
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 57
    Points : 26
    Points
    26
    Par défaut
    euh avec ca quand le dernier message aura ete recu, on retournera dans la boucle et l'application se blokera en attente d'un message non ?

  6. #6
    Membre régulier Avatar de psyphi
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    119
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Allemagne

    Informations professionnelles :
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2006
    Messages : 119
    Points : 120
    Points
    120
    Par défaut
    Non quand le dernier message est reçu le serveur coupe la communication et donc recv reçoit rien (0).
    Lis un peu de doc:
    http://psyphi.zeblog.com/131309-tuto...r-les-sockets/

    et notamment cette source qui est ce que tu veux faire:
    http://sylvainmarechal.chez-alice.fr...tcp/http/get.c

  7. #7
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    57
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 57
    Points : 26
    Points
    26
    Par défaut
    ben c'est parce qu'il met connection:close dans le header de sa requete.
    Moi j'ai pas forcément envie de fermer la connection parce que je vais répondre au message envoyé par le serveur...

  8. #8
    Membre régulier Avatar de psyphi
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    119
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Allemagne

    Informations professionnelles :
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2006
    Messages : 119
    Points : 120
    Points
    120
    Par défaut
    Ba laisse un connection: Keep-Alive mais je vois pas trop ce que tu veux répondre au serveur ?!
    Tu lui envoie une requête puis il t'envoie une réponse avec une page ou un code d'erreur. Je vois pas ce que tu peux ensuite répondre à sa réponse. Ce n'est plus du http après.

  9. #9
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    57
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 57
    Points : 26
    Points
    26
    Par défaut
    mais si je laisse le keep alive, j'aurai le problème du prog qui se bloque en attendant une réponse avec le recv();


    sinon moi j'ai besoin de renvoyer une requete en fonction de la reponse et j'aimerais eviter de devoir reinitialiser la connection a chaque fois

  10. #10
    Membre régulier Avatar de psyphi
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    119
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Allemagne

    Informations professionnelles :
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2006
    Messages : 119
    Points : 120
    Points
    120
    Par défaut
    Dit en un peu plus sur le but de ton programme.
    Elle sera de quelle forme la réponse du serveur juste des headers dans ce cas tu peux détecter les "\r\n\r\n" ou bien aussi une page html?

  11. #11
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    57
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 57
    Points : 26
    Points
    26
    Par défaut
    je veux faire un programme qui soit capable de dialoguer avec n'importe quel serveur, http ou pas, mais qui prenne en compte le fait que les réponses peuvent arriver en plusieurs fragments. De plus, je souhaiterais ne pas avoir à réinitialiser la connection a chaque fois, ce qui m'empêche d'employer la boucle décrite plus haut

  12. #12
    Membre régulier Avatar de psyphi
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    119
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Allemagne

    Informations professionnelles :
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2006
    Messages : 119
    Points : 120
    Points
    120
    Par défaut
    Citation Envoyé par TheShade
    je veux faire un programme qui soit capable de dialoguer avec n'importe quel serveur, http ou pas
    Bonne chance , t'en as pour des années je pense.

    Citation Envoyé par TheShade
    ce qui m'empêche d'employer la boucle décrite plus haut
    Ce qui t'empêche d'utiliser la boucle plus haut c'est que tu ne sais comment se termine la connexion avec serveur. Chaque protocole HTTP/FTP/SMTP... se termine de façon différente, c'est donc à toi d'implémenter tout les protocoles pour ton client afin qu'il accepte tout les serveurs possible , c'est pourquoi je pense que tu n'es pas sortit de l'auberge.

    La seule façon de recevoir tout les paquets d'un serveur qui les fragmentes est de faire une boucle sur un recv(), ensuite il y a différente façon de terminer la boucle ça dépend du protocole. Et le pire c'est qu'il est possible que les protocoles se croisent !! J'entends par là que si par exemple un protocole utilise la chaine "\r\n\r\n" pour dire par exemple "va renvoyer des paquets" le protocole HTTP va la comprendre comme "Fin d'émission de la requête".
    Pour en savoir plus sur les différents protocole lis les RFC.

    Désolé mais je ne pense pas pouvoir d'aider plus loin.

  13. #13
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    57
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 57
    Points : 26
    Points
    26
    Par défaut
    merci tu as bien répondu à ma question
    je me suis mal exprimé en disant que je voulai qu'il supporte tous les protocoles en même temps, je voulai simplement savoir s'il existait une méthode qui soit indépendante du protocole, la réponse est non, je te remercie

  14. #14
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    57
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 57
    Points : 26
    Points
    26
    Par défaut
    Bon j'ai parfaitement réussi à programmer mon client http.
    Cependant un problème survient lorsque la réponse est en fait un fichier (une image par exemple), qui contient des caractères NULL.
    En effet, mon string (buffer) ne prend plus en compte ce qu'il a recu après ce NULL, que ce soit pour l'écriture dans un fichier, l'affichage, ou même l'accès par l'opérateur [].
    Comment faire ?

  15. #15
    Membre régulier Avatar de psyphi
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    119
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Allemagne

    Informations professionnelles :
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2006
    Messages : 119
    Points : 120
    Points
    120
    Par défaut
    Il faut que tu traites le buffer non pas comme une string mais comme un flux de données binaires.
    Quand tu reçois les données, tu dois faire un code qui ressemble à ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    FILE * fd;
    char buffer[1024+1];
     
    ...
     
    while((length=recv(socket,buffer, sizeof(buffer)-1,0)) > 0)
    {
            buffer[length] = 0;
    	fwrite(buffer, sizeof(buffer)-1, length,fd);
    	size += length;
    	printf("Recu: %d\n",length);
    	memset(buffer,'\0', sizeof(buffer));
    }

  16. #16
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    57
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 57
    Points : 26
    Points
    26
    Par défaut
    bon je vais essayer le problème c'est que j'aurais aimé faire cela avec un string, pas un char*.
    Dans ce cas, pour fwrite, je dois indiquer buffer.c_str(), qui me retourne seulement la chaine juskau premier caractere NULL, les suivants étant plusou moins aléatoires, donc la méthode de forcer le nombre de donées à écrire avec fwrite ne fonctionne pas.

  17. #17
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Si tu veux gérer une zone binaire dynamique, plutôt que string, qui a une notion de chaine de caractères mal adaptée, plutôt qu'un char*, qui demande une gestion de mémoire à la main (encore que si le buffer est de taille fixe...), tu peux utiliser un vector<unsigned char>.

  18. #18
    Expert éminent

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Points : 7 618
    Points
    7 618
    Billets dans le blog
    3
    Par défaut
    En même temps, le protocol HTTP spécifie que la longueur en octet doit être spécifiée dans le champ "Content-Length" du header...

    Une fois le header lu, on doit savoir la taille de ce qui suit... à une exception pret, quant le serveur renvoit la réponse par blocs (Content-Type). Là c'est plus galère à gérer vu qu'on ne sait pas à l'avance la taille globale.

    Mais bon, chaque bloc indique sa taille donc c'est pas non plus particulièrement difficile. Il faut juste faire un peu de buffering mémoire... (quite à utiliser du realloc en C).

Discussions similaires

  1. réseau: problème modem ADSL, DHCP et SP2 (sig!)
    Par p0Kep0K dans le forum Dépannage et Assistance
    Réponses: 4
    Dernier message: 26/10/2005, 21h11
  2. Réponses: 5
    Dernier message: 24/09/2005, 21h31
  3. [Réseau] Problème entre X-DOS et Windows 98
    Par FLCEOAP dans le forum Développement
    Réponses: 1
    Dernier message: 16/05/2005, 00h41
  4. [résolution de noms] [réseau] problème fichier hosts
    Par Aldo dans le forum Administration
    Réponses: 2
    Dernier message: 11/04/2005, 22h38
  5. [Réseau] Problème socket
    Par neenee dans le forum Entrée/Sortie
    Réponses: 14
    Dernier message: 18/01/2005, 16h26

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo