Socket recv incomplet

Bonjour,

Voila j'ai un programme qui utilise des sockets
et je doit recevoir un fichier assez gros 2Mo
je problème c'est que je ne voudrai pas mettre un buffer de 2Mo
Mais que ma fonction reçoivent les données jusqu'à ce qu'il n'y en ai plus

y a t'il une fonction qui permet de savoir si il reste des données a lire sur ma socket ?

Merci

14 réponses

  1. Contributeur
    pour avoir une socket non bloquante, il faut utiliser fcntl http://www.linux-kheops.com/doc/man/manfr/man-html-0.9/man2/fcntl.2.html avec l'argument O_NONBLOCK
    Ensuite, tu peux utiliser select pour attendre les premières données normalement. http://www.linux-kheops.com/doc/man/manfr/man-html-0.9/man2/select.2.html
    Ensuite, il faut combiner le tout avec un timeout.
    Je ne peut pas plus t'aider, je ne me suis jamais aventurer là dedans, je préfère trouver d'autre solutions (dans ton cas, j'utiliserai Qt et ses fonctions HTTP). Mais en faisant des recherche supplémentaire avec ces mots clefs plus ceux que tu trouvera dans les liens, tu devrais pouvoir t'en sortir.
    0
    1. Oui je veux bien tes liens
      Oui oui c est sur linux.
      0
      1. Contributeur
        bon, en effet, si tu ne fait pas le serveur, il faut surement passer par une socket non bloquante...
        Win ou Linux ? Sous Linux, je peut te donner quelques liens.
        0
        1. tien voila ce que j ai fais :

          std::string tHTTP::ReceiveHTML(int Descripteur)
          {
              char Buffer[1024];
              char *DataRecu;
              std::string DataFinal = "";
              int continuer = 1;
              while(continuer == 1)
              {
                  int ResultRecv = recv(Descripteur, Buffer, sizeof(Buffer),0);
                  if (ResultRecv < 0)
                  {
                      std::cout << " [*] ERR : Reception des donnees impossible " << std::endl;
                      perror("recv");
                  }
                  else
                  {
                            DataRecu = new char[strlen(Buffer) + 1];
                            strcpy(DataRecu,Buffer);
                            std::string result = DataRecu;
          
                            DataFinal = DataFinal + result;
          
                  }
          
                  if (ResultRecv != strlen(Buffer))
                      continuer = 0;
              }
          
              return DataFinal;
          }
          


          Par contre je ne reçoit toujours pas toute une page.
          0
          1. Contributeur
            en fait, tu veux dire en disant HTTP que tu ne code pas le serveur. C'est ça ?
            tu peut récupérer la taille d'un fichier avec les requetes http://www.siteduzero.com/tutoriel-3-35613-les-requetes-http.html#ss_part_3
            Sinon, une boucle du genre :
             int ResultRecv = recv(Descripteur, Buffer, sizeof(Buffer),0);
            while(ResultRecv==1024)
                 ResultRecv = recv(Descripteur, Buffer, sizeof(Buffer),0);
            
            0
            1. oui je transmet des chaine de caractère
              j avais en effet essayer avec une boucle mais sa ne marchai sa terrible

              et pour le mot particulier je ne pense pas que sa soit possible les fichier sont récupérer sur un serveur Web donc par HTTP.

              et en effet strlen(Buffer) et ResultRecv on la même taille
              mais je ne vois pas quoi en faire ? les mettre en tant que condition dans ma boucle ?
              0
              1. Contributeur
                Je ne comprend pas, tu n'as pas de boucle...
                Tu transmet bien des chaines de caractères ?
                compare strlen(Buffer) et ResultRecv , ils doivent avoir la même taille.

                Sinon, tu peut convenir que lorsque le serveur a terminé de t'envoyer le fichier il emet un mot particulier qui terminera la transmission.
                0
                1. Voici le code de la fonction qui recupere les info

                  std::string tHTTP::ReceiveDATA(int Descripteur)
                  {
                      char Buffer[1024];
                      char *DataRecu;
                      int ResultRecv = recv(Descripteur, Buffer, sizeof(Buffer),0);
                      if (ResultRecv < 0)
                      {
                          std::cout << " [*] ERR : Reception des donnees impossible " << std::endl;
                          perror("recv");
                      }
                      else
                      {
                                DataRecu = new char[strlen(Buffer) + 1];
                                strcpy(DataRecu,Buffer);
                      }
                  
                      std::cout << " [*] VAR : Descripteur = " << Descripteur << std::endl;
                      std::cout << " [*] VAR : Data Recu = " << DataRecu << std::endl;
                  
                      std::string result = DataRecu;
                      return result;
                  }
                  0
                  1. Contributeur
                    pour connaitre la taille d'un fichier :
                    https://forum.hardware.fr/hfr/Programmation/taille-fichier-sujet_15390_1.htm
                    C'est sur que si au moment où le serveur ouvre le fichier celui-ci n'est pas complet ça complique l'affaire.
                    Je pense à un truc, si tu fait sous windows, il me semble qu'il y a un truc à la con qui stoppe l'envoie des des données ou leur réception lorsque l'on tombe sur des retours à la ligne ou des zéros.
                    Met ton code, on y verra plus clair s'il bug.
                    0
                    1. Alors j ai essayer plusieurs chose
                      premièrement il m est impossible de connaitre la taille du fichier car il sont télécharger via un site donc via HTTP. et sinon ma boucle de recv bug un peu
                      0
                      1. ok merci je vais testé plusieurs de ces solutions je te tiens au courant =)
                        0
                        1. Contributeur
                          non, pas tordu au sens purement algorithmique, mais chiant à faire en socket.
                          Pour des données de taille variable, soit tu fais comme je t'ai dit, en testant le recv.
                          Sinon, il y a d'autres technique. Récupérer la taille du fichier et envoyer au client. Donc, tu fait un recv qui récupère la taille des données, tu dimensionne ton buffer, tu récupères les données.
                          Sinon, tu fait un mini protocole : tu reçoit les données, demandes au serveur s'il y en a d'autre, soit il répond non et c'est fini, soit il répond oui et tu reçoit un autre paquet de données.
                          Ce ne sont que des idées qui me viennent sur le vif, mais il doit y a voir d'autres solutions.
                          0
                          1. ici mon fichier fais 2Mo
                            la il doit en télécharger plusieurs
                            qui n'ont pas tous la même taille
                            et on ne connais pas cette taille a l avance
                            donc je trouve pas sa si tordu si ?
                            ou s il y a un moyen plus simple ?
                            0
                            1. Contributeur
                              un peut tordu.
                              Je pense que si tu fait un buffer de taille x, tu fait une boucle sur les recv, et tant que recv te renvoi x comme taille lu, alors il reste des données à lire.
                              Je ne suis pas certain, mais ça peut fonctionner.
                              0