Partage
  • Partager sur Facebook
  • Partager sur Twitter

Envoi de fichiers de tout types en C++ via sockets

    22 décembre 2022 à 17:45:56

    Bonjour !
    Je viens sur le forum car je bloque depuis quelques temps sur un problèmes auquel je ne parviens pas à trouver de solution.
    J'aimerais envoyer et recevoir via des sockets (j'utilise winsock) des fichiers de tout type. Je sais qu'on ne peut pas envoyer "directement" un fichier, il faut plutôt envoyer son contenu. Pour ça, j'utilise fstream pour lire et écrire dans les fichiers, que j'ouvre en binaire en spécifiant "std::ios::binary" en paramètre de la fonction open de mon flux. Donc je lis le fichier, le stocke dans un tableau de char puis l'envoie via la socket, puis la machine destinataire réceptionne le contenu et l'écrit dans un nouveau fichier de son côté. Et c'est là où j'ai un problème :
    Ca fonctionne parfaitement avec un .txt, du coup j'ai ensuite voulu testé avec un .exe. Avec un éditeur héxadécimal, j'ai vu que ce fichier executable commençait par "4d5a". Je procède à l'envoi de ce fichier, mais le nouveau fichier .exe que le programme destinataire créer contient seulement "MZ" (traduction de 4d5a en texte) ! Et je ne comprend pas comment c'est possible de passer du code hexa aux caractères correspondant alors que les deux fichiers sont ouverts de la même façon en "std::ios::binary" et qu'ils sont tous deux des fichiers .exe, donc devraient être lu de la même manière. J'ai regardé dans le fichier d'origine ce qu'il y avait ensuite, et les caractères qui suivaient ne font pas partie de la table de caractère, du coup je pense que c'est quand je stocke le fichier dans un tableau de char que ça passe pas. Donc je me suis dit que j'avait juste à stocker ça dans un vector d'int... sauf que je peux pas envoyer des int via ma socket, il veut forcément un tableau de char...
    Du coup j'ai pensé que puisque tout ce qu'envoie une socket, c'est une suite d'octets, pourquoi ne peut stocker les données binaires brutes de mon executable et les envoyer directement, sans les interpréter en aucun type, que ce soit bool, int, char etc...
    Sauf que je sais pas comment faire ça, j'ai fait beaucoup de recherches mais aucune parle de stocker des données bianires directement... Donc je demande de l'aide ici.
    Merci par avance.
    P.S : "l'éditeur héxadécimal" dont je parlais un peu plus tôt est Sublime Text. Je sais qu'en vrai c'est pas vraiment un éditeur héxadécimal mais quand j'ouvre un exe avec il m'affiche bien son code héxa. C'est pour ça que dans le fichier exe d'origine il m'affiche de l'hexa mais que dans les fichier exe copié il l'affiche en texte.
    • Partager sur Facebook
    • Partager sur Twitter
      22 décembre 2022 à 21:56:58

      Winsock, c'est du C, pas du C++.

      Pourquoi ne pas utiliser une "vraie" librairie de communication en C++, plutôt que de réinventer une roue carrée.

      Un fichier et son "Contenu", c'est loin d'être la même chose : le nom du fichier, les droits sur les fichiers, les stream auxiliaires d'un fichier, etc...

      On n'est plus dans les années 70 sous Unix (et encore).

      Donc votre truc, c'est un joujou des années patte-d'ef.

      >Je sais qu'on ne peut pas envoyer "directement" un fichier

      Si c'est possible, si vous utilisiez une librairie qui à moins de 40 ans. (Ca me rajeuni pas)

      >que j'ouvre en binaire en spécifiant "std::ios::binary" en paramètre de la fonction open de mon flux.

      Ca c'est pour que l'OS ne fasse pas automatiquement des "conneries" à la volée sur les données, mais cela ne garantit pas que vous ne les faites pas.

      Votre code, SVP.

      >Donc je me suis dit que j'avait juste à stocker ça dans un vector d'int... sauf que je peux pas envoyer des int via ma socket

      Sachant que le format des entiers n'est pas un standard (little endian vs big endian, etc...), c'est vraiment pas une bonne idée, vraiment pas.

      >il veut forcément un tableau de char...

      On parle d'une librairie qui à plus de 40 ans, près de 20 ans la standardisation du C++. LOL

      >Du coup j'ai pensé que puisque tout ce qu'envoie une socket, c'est une suite d'octets

      Absolument faux, cf. Caractères hors bande, les packet UDP, etc...

      Bon, vous avez une vie complètement "Dunning-Kruger" du sujet.

      On commence par le début, utilisez un sniffer réseau type WireShark pour savoir si le problème est dans l'émetteur ou dans le receveur ou les 2.

      Puis utilisez le débogueur pour analyses ce que fait votre code "concrètement".

      • Partager sur Facebook
      • Partager sur Twitter
      Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
        28 décembre 2022 à 12:30:57

        bacelar a écrit:

        Pourquoi ne pas utiliser une "vraie" librairie de communication en C++, plutôt que de réinventer une roue carrée.


        Parce que j'en ai cherché et je n'en ai pas trouvé en dehors des framework.

        bacelar a écrit:

        Absolument faux, cf. Caractères hors bande, les packet UDP, etc...


        Mais en informatique tout n'est pas qu'une suite de bits et d'octets ?

        -
        Edité par Yixraie 28 décembre 2022 à 12:34:58

        • Partager sur Facebook
        • Partager sur Twitter
          28 décembre 2022 à 19:07:16

          Salut,

          De base, tu n'as pas tord: tout en informatique n'est jamais qu'une suite de bits, regroupés en octets.

          Seulement, cela revient en gros à dire que vous et moi, la vache qui broute dans son champs et le vers de terre ne sont que ... des amas de cellules vivantes.

          C'est fondamentalement vrai, mais cela n'aide pas vraiment à se faire une idée précise de ce qu'est "la vie" ;)

          Le socket n'est que la "toute première couche" du système, celle qui va permettre à deux partie "hardware" (matérielles) de se retrouver et de communiquer entre elles alors qu'elles ne sont, potentiellement, pas forcément sur le même ordinateur.

          Seulement, au dessus (ou à coté) de cette couche, il y en a d'autres comme les protocoles "TCP/IP", UDP, FTP, HTTP(S) et bien d'autres qui, en plus de permettre l'envoi des donnée d'un socket à l'autre vont aussi permettre au matériel d'envoyer à son destinataire des informations sur "ce qui se fait pour l'instant", sur "ce que j'attends maintenant de ta part" ou même de dire que "là, je répond à la question que tu m'as posée" ou bien d'autres choses encore.

          Ces protocoles sont, pour certains, particulièrement complexes à mettre en oeuvre. mais tous on cette particularité d'être absolument indispensables pour s'assurer que deux machines seront en mesure de communiquer entre elles, surtout qu'il y a  -- parfois -- un océan qui les sépare.

          • Partager sur Facebook
          • Partager sur Twitter
          Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs  à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
            28 décembre 2022 à 19:10:34

             >Parce que j'en ai cherché et je n'en ai pas trouvé en dehors des framework.

            Vous vous foutez de nous ???

            https://letmegooglethat.com/?q=network+library+c%2B%2B

            Question con, c'est quoi un "framework" pour vous ?

            >Mais en informatique tout n'est pas qu'une suite de bits et d'octets ?

            Bin, vous, vous êtes pas fait pour le virage quantique de l'informatique ou avec des capteurs analogiques.

            C'est vrai que les dimensions temporelles, probabilistiques, structurelles, etc.. c'est surfait.

            Sortez votre tête de votre syndrome "Dunning-Kruger".

            Non, portez un nom proche d'un framework ne fait pas d'une librairie un framework.

            Non, il n'y a pas que des 0 et des 1 ou des octets en informatique.

            Si vous voulez des conseils consensuels, demandez à chatGPT.

            Bon, vous avez évalué un truc comme boost.asio ?

            Pourquoi un truc comme le protocole FTP ne vous convient pas ?

            Sinon, si vous insistez avec votre machin antique, bin répondez aux questions : constats avec WireShark et avec le débogueur.

            • Partager sur Facebook
            • Partager sur Twitter
            Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
              29 décembre 2022 à 12:35:46

              Bonjour !

              Je me mêle un peu de ce sujet alors que je fais rarement du réseau, mais depuis C++ 11 ou 14 ou je ne sais lequel, il  n'y a pas des fonctionnalités réseau en std:: directement ? 

              (car comme l'auteur, moi j'en étais resté aux sockets. En même temps je n'ai pas du toucher à de la prog réseau depuis... oula.... des années !)

              • Partager sur Facebook
              • Partager sur Twitter

              Recueil de code C et C++  http://fvirtman.free.fr/recueil/index.html

                30 décembre 2022 à 16:58:07

                Bonjour, merci pour vos retours.

                J'ai trouvé l'API libcurl mais je ne sais pas si c'est une bonne idée. Qu'en pensez vous ?

                • Partager sur Facebook
                • Partager sur Twitter
                  31 décembre 2022 à 17:12:36

                  Libcurl, c'est pour du HTTP.

                  C'est toujours du C, mais c'est plus "moderne" et plus simple à utiliser car de plus "haut niveau" et plus limitée.

                  • Partager sur Facebook
                  • Partager sur Twitter
                  Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                    2 janvier 2023 à 20:51:46

                    Ok merci pour la réponse.

                    J'aimerais utiliser une librarie vraiment C++, est-ce le cas de boost.asio ? Est-ce que cette bibliothèque permet le transfert de fichiers ?

                    EDIT :

                    Désolé Fvirtman j'ai complètement oublié de te répondre... Non la bibliothèque standard n'inclût pas de fonctionnalités réseau.

                    -
                    Edité par Yixraie 2 janvier 2023 à 20:54:13

                    • Partager sur Facebook
                    • Partager sur Twitter
                      3 janvier 2023 à 1:30:23

                      >J'aimerais utiliser une librarie vraiment C++, est-ce le cas de boost.asio ?

                      Oui

                      >Est-ce que cette bibliothèque permet le transfert de fichiers ?

                      On peut tout faire avec n'importe quoi, ça prend juste beaucoup beaucoup plus de temps.

                      "boost.asio" ne fait que la communication réseau, et le fait bien.

                      Un fichier, que cela vous plaise ou non, c'est pas juste une suite d'octets. Donc rien de vraiment portable sans "problèmes".

                      L'utilisation de protocole de plus haut niveau, type FTP, permet de réduire l'impact (gravité, fréquence, ...) de ces problèmes (droits, encodage, décryptage, compression, etc...).

                      En faisant des choix (protocoles, restriction d'usage, etc...) vous aurez des librairies plus spécialisées mais qui vous mâchent bien plus le travail (libcurl en est un exemple, même si elle est en C).

                      • Partager sur Facebook
                      • Partager sur Twitter
                      Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                        3 janvier 2023 à 18:28:12

                        Ok merci, je test avec boost.asio et si j'y arrive pas je prendrai une bibliothèque spécialisée pour FTP.
                        • Partager sur Facebook
                        • Partager sur Twitter
                          3 janvier 2023 à 19:02:08

                          Les trucs que ne gèrent pas les librairies "bas-niveau" mais les librairies/protocoles de haut niveau devraient gérer, c'est des trucs comme la gestion de l'encodage des caractères de fin de ligne dans les "fichiers textes", l'horodatage des fichiers, gestion des fichiers "multi-stream", etc...

                          Mais les trucs comme les "attributs MSDOS : hiden, archived, etc), ou des sticky-bits sous Unix, la gestion des droits par groupe d'utilisateur, etc..., ne seront pas gérer, même par des librairies/protocoles "haut-niveau".

                          • Partager sur Facebook
                          • Partager sur Twitter
                          Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                            17 janvier 2023 à 21:11:13

                            Bonjour !

                            J'ai testé mon programme avec Boost.Asio, mais je ne sais pas trop comment procéder au transfert de fichier...

                            Je pense que je dois sérialiser le contenu du fichier dans une archive binaire afin de l'envoyer sur le réseau, puis le récepteur devra désérialiser et écrire le contenu dans un nouveau fichier.

                            Seulement, je me heurte encore au problème qui est que je ne peux pas stocker le contenu de mon fichier dans une chaîne de caractère...

                            Sauriez-vous comment faire ? Merci par avance

                            -
                            Edité par Yixraie 17 janvier 2023 à 21:11:47

                            • Partager sur Facebook
                            • Partager sur Twitter
                              17 janvier 2023 à 21:28:38

                              (toutes les discussions autour de la lib de socket employée, c'est du pinaillage sans rapport avec ton problème exprimé -- ce qui n'empêche pas qu'il est tout à fait possible que l'"exe" que tu fais transiter entre tes 2 machines ne pourra pas être exécuté en cas d'environnement différent)

                              Bref. La clé, si on ignore l'endianess et plein d'autres choses.

                              1- tu obtiens la taille de ton fichier

                              2- (en supposant qu'elle ne soit pas délirante; boucle avec readsome sinon?), tu alloues un vecteur de char de la taille en question

                              3- tu crées/ouvres bien un std::ifstream avec le flag "n'interprète pas, c'est pas du texte (aka binary)"

                              4- tu lis avec std::istream::read vers le début du vecteur (surtout pas les lectures qui décodent avec >> -- mon intuition est que tu joues avec ça)

                              5- tu fais ce qu'il faut faire côté réseau, et sur la socket tu dumpes le vecteur. Le truc intelligent à faire avant: convenir d'un protocole pour indiquer combien il y a d'octets à recevoir (et qui vont donc être émis) (c'est là que la gestion de l'endianess peut avoir son importance)

                              Et de l'autre côté; le read de la taille, création du vecteur bien dimensionné, read des octets dans le vecteur. Et dump avec ostream::write dans un fichier ouvert en mode binaire.

                              Et si l'OS diffère trop, qu'il n'y a pas les bonnes dépendances/libs... pas impossible que le truc récupéré ne puisse pas être exécuté... Normal. Quant aux droits... ah ah ah. On verra ça quand tu auras trouvé comment manipuler des séquences d'octets et les échanger.

                              PS: Je sais que les protocoles binaires réseaux et fichiers manipulent des char, mais il ne faut pas les voir comme des caractères, mais comme des octets (je continue à penser que c'est unsigned char (std::byte en C++20) qu'il faudrait pour ces protocoles)

                              -
                              Edité par lmghs 17 janvier 2023 à 23:25:46

                              • Partager sur Facebook
                              • Partager sur Twitter
                              C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
                                18 janvier 2023 à 14:15:33

                                lmghs a écrit:

                                PS: Je sais que les protocoles binaires réseaux et fichiers manipulent des char, mais il ne faut pas les voir comme des caractères, mais comme des octets


                                Mais dans tout les cas, si l'octet que je lis n'existe pas dans la table de caractères, je peux pas le stocker dans un char... si ?

                                Et du coup, la sérialisation avant d'envoyer sur le réseau ne sert à rien ?

                                -
                                Edité par Yixraie 18 janvier 2023 à 14:16:22

                                • Partager sur Facebook
                                • Partager sur Twitter
                                  18 janvier 2023 à 14:37:14

                                  char, c'est le type le plus petit pour stocker des nombres. Sur nos machines ça peut varier entre -128 et 127, ou 0 et 255. Ca dépend. Et bref, c'est un nombre.

                                  Nombre qui connait un traitement spécifique de la part des fonctions d'affichage: il est transformé en caractère (je vais simplifier) qui correspond (à ce nombre) dans la table d'encodage courante de la console (j'ai dit que je simplifiais). Et vu que les 27 premières valeurs n'ont aucune association graphique, et qu'au delà de 128 c'est le bordel, pour afficher des séquences d'octets, on va prendre ces nombres isolément pour afficher leur valeur numérique en représentation textuelle hexadécimale (et il y a plein de programmes qui font ça très bien)

                                  Après donc, sur nos machines courantes (!), un char permet de stocker un octet -- sur nos PC, le char est garantit d'être défini avec exactement 8 bits.

                                  Tout ça pour dire, que tu as de mauvaises définitions/compréhension des diverses choses que l'on peut faire d'un char, ce que cela peut désigner, etc.

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                  C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
                                    18 janvier 2023 à 17:24:52

                                    Ok, merci pour l'information ! Je tente et je vous dirai si je rencontre d'autres problèmes.
                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      16 février 2023 à 14:12:55

                                      Bonjour.

                                      Merci beaucoup à vous, j'ai compris comment faire passer des fichiers par le réseau ! Mais maintenant je rencontre des problèmes d'optimisation...

                                      Lorsque je veux faire passer un fichier de grande taille, et que je dois le découper en plusieurs morceaux, je ne sais pas en combien de morceaux le diviser afin d'obtenir les meilleurs résultats... je pense qu'l vaut mieux faire le moins de morceaux possible, mais en même temps cela m'obligerais à envoyer des paquets très lourds.

                                      Comment feriez-vous ?

                                      -
                                      Edité par Yixraie 16 février 2023 à 14:13:52

                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        16 février 2023 à 15:44:09

                                        C'est le genre de bidouille que gèrent, de manière assez complexe, les protocoles de niveau 4 (Transfert) du modèle OSI de l'ISO, comme TCP.

                                        Qu'est-ce qui ne va pas dans les mécanismes d'optimisation du flux offerts par TCP ?

                                        Mode relou : une librairie spécialisée dans l'échange de fichier le ferait pour vous, si vous déniez ne pas réinventer une roue carrée.

                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                        Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                                          16 février 2023 à 18:46:13

                                          Rebonjour.

                                          Tout compte fait, je n'avait pas testé le transfert de fichiers correctement, je n'y suis pas parvenu en fait....

                                          Quand je tente de transférer un fichier exe ou image, j'ai un message me disant que les données sont "corrompues" lorsque je tente d'ouvrir le fichier qui vient d'être créé par mon programme.

                                          Alors j'ai essayé d'afficher les données transmises dans la console au moment où elles le sont et, très étrangement, je vois apparaître des "Ios", des "basic_istream", et d'autres noms dans ce style par ci par là...

                                          Je ne comprend pas trop ce que ça signifie, mais le plus étrange est que le fichier en destination a exactement la même taille que le fichier source.

                                          -
                                          Edité par Yixraie 16 février 2023 à 18:46:39

                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                            17 février 2023 à 11:04:09

                                            La taille n'est vraiment pas un bon indicateur de la transmission correcte des données, un MD5 est bien plus fiable.

                                            La console, c'est vraiment pas un bon outil de debug.

                                            Si la plateforme d'envoi et de réception ne sont pas les mêmes (version d'outils et configuration d'outils, etc...), le fait que l'une n'arrive à utiliser le fichier et pas l'autre n'implique pas une erreur de transmission, ça peut être juste que la plateforme de réception n'est pas configuré de la même manière (32bits vs 64bits, version de Dll, version de viewer d'image, etc...).

                                            Utilisez le débogueur et/ou un sniffer réseau.

                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                            Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                                              17 février 2023 à 11:32:31

                                              bacelar a écrit:

                                              Si la plateforme d'envoi et de réception ne sont pas les mêmes


                                              Le problème ne viens pas de là, car je n'ai pour l'instant testé qu'en faisant tourner serveur et client sur la même machine (je ne suis même pas passé par le réseau, j'ai utilisé l'adresse locale 127.0.0.1 pour connecter le client au serveur).

                                              Je n'ai pas encore essayé d'utiliser le sniffer réseau, je fais ça de suite.

                                              • Partager sur Facebook
                                              • Partager sur Twitter
                                                17 février 2023 à 11:37:05

                                                Sur l'adresse de loopback (127.0.0.1), un sniffer réseau risque d'être compliqué à configurer, le débogueur est une option mais pourquoi ne pas simplement utiliser un utilitaire de comparaison de fichier ???
                                                • Partager sur Facebook
                                                • Partager sur Twitter
                                                Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                                                  17 février 2023 à 12:41:57

                                                  Au final j'ai réussi à capturer le trafic entre serveur et client grâce au sniffer. Il me montre exactement la même chose que j'avait déjà vu dans la console, c'est-à-dire des "basic_istream", des  "char_traits" et autres noms dans ce goût là...

                                                  En revanche, j'ai tenté d'utiliser un utilitaire de comparaison de fichier et... il a eu la bonne idée de m'afficher l'exe en destination sous forme de texte ! En fait, je me suis rendu compte que le problème vient du fait que mon programme s'embrouille avec les anciens paquets envoyés, et le fichier en destination est en fait rempli des centaines de fois du contenu d'anciens paquets échangés par les programmes ! En revanche je ne comprend pas pourquoi le problème ne survient pas avec les fichiers texte... et pourquoi ce que je vois dans la console n'est pas ce que je vois dans le fichier.

                                                  -
                                                  Edité par Yixraie 17 février 2023 à 12:52:35

                                                  • Partager sur Facebook
                                                  • Partager sur Twitter
                                                    17 février 2023 à 16:06:21

                                                    >Il me montre exactement la même chose que j'avait déjà vu dans la console, c'est-à-dire des "basic_istream", des  "char_traits" et autres noms dans ce goût là...

                                                    Ce n'est donc pas qu'un mauvais usage de la console en sortie du client, le problème initial est côté serveur.

                                                    >je me suis rendu compte que le problème vient du fait que mon programme s'embrouille avec les anciens paquets envoyés

                                                    Si les "embrouilles" sont visibles dans le sniffer, c'est que le problème initial est côté serveur.

                                                    >En revanche je ne comprend pas pourquoi le problème ne survient pas avec les fichiers texte

                                                    Si le problème, c'est que vous convertissez le contenu en texte, le binaire se fait maravé pour entrer dans du texte, mais le texte se fait convertir "en lui-même'.

                                                    >et pourquoi ce que je vois dans la console n'est pas ce que je vois dans le fichier.

                                                    Comme déjà indiqué, la console n'est pas un outil de debugging. (mise en forme en fonction de la configuration de console, etc...)

                                                    Votre code serveur SVP.

                                                    • Partager sur Facebook
                                                    • Partager sur Twitter
                                                    Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                                                      17 février 2023 à 17:20:33

                                                      bacelar a écrit:

                                                      Si le problème, c'est que vous convertissez le contenu en texte


                                                      Il ne me semble pas, j'utilise le flag std::ios::binary lors de l'ouverture de mon fichier, et je n'effectue aucun traitement sur les données entre le moment où je les reçoit et le moment où je les écrits dans le fichier (en fait je ne fait rien du tout entre les deux).
                                                      • Partager sur Facebook
                                                      • Partager sur Twitter
                                                        17 février 2023 à 17:41:05

                                                        >où je les reçoit et le moment où je les écrits dans le fichier

                                                        Non mais ça c'est coté client, le problème est vraisemblablement serveur.

                                                        Votre code serveur SVP. (BIS)

                                                        • Partager sur Facebook
                                                        • Partager sur Twitter
                                                        Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                                                          18 février 2023 à 13:18:50

                                                          Yixraie a écrit:

                                                          Il ne me semble pas, j'utilise le flag std::ios::binary

                                                          C'est justement là que tu te trompes, et l'origine de tous tes problèmes...

                                                          Car lorsque ce flag est absent, cela implique que tu veuiles ouvrir le fichier de manière à ce que son contenu puisse être représenté sous une forme compréhensive par l'humain, et donc qu'il y aura tout un processus de conversion qui sera exécuté sans même que tu ne t'en apercoives.

                                                          En effet, pour que la représentation du fichier puisse être "compréhensible par l'humain", le système va prendre chaque valeur numérique présente dans le fichier et l'utiliser pour déterminer quel "glyphe" ( du symbole ) qui devra être tracé à l'écran pour que l'humain soit en mesure de le lire.  Et pour ce faire, il va se baser sur "une table de conversion", comme la table ASCII (par exemple).

                                                          Ainsi, si le système trouve la valeur 43 (en décimale, pour la facilité) dans le fichier, ce sera le glyphe correspondant au chiffre 0 qui sera affiché, et, s'il trouve la valeur 90 (en décimale, toujours), il affichera la lettre z en majuscule.

                                                          Le gros problème, c'est qu'il y a une série de valeurs qui ne correspondent pas à un glyphe susceptible d'être afficher, mais bien à des "instructions" qui permettaient à des systèmes comme les téléscripteurs de fonctionner.

                                                          Ainsi, la valeur 7 sera convertie en "une sonnerie" ("beep") pour indiquer qu'il y a un appel, et la valeur 8 sera convertie en ... un retour arrière ou que la valeur 13 impliquera que le "système d'impression (d'affichage) doit ... retourner au début de la ligne.

                                                          Le flag std::binary permet de dire au système quelque chose comme " je ne veux pas que tu me convertisse le contenu du fichier dans une forme compréhensible par l'humain" ou, si tu préfères, de dire au système "si tu trouve des valeurs  comme 8, 10, 13 ou 90 (ou n'importe quelle autre), je veux que tu utilises effectivement ces valeurs sans essayer d'aller voir dans la table de caractères à quoi elles correspondent".

                                                          Et c'est le seul moyen dont tu dispose pour t'assurer que "le système" ne fera rien de plus que de récupérer les valeurs telles qu'elles arrivent dans le fichier.

                                                          Quelque part, nous pourrions presque regretter que l'ouverture des flux ne se fasse pas avec le flag std::binary par défaut, mais bon, il s'agit d'un problème historique hérité du C depuis l'origine des temps, et il serait difficile de changer ce fait ...

                                                          • Partager sur Facebook
                                                          • Partager sur Twitter
                                                          Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs  à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
                                                            20 février 2023 à 17:20:10

                                                            koala01 a écrit:

                                                            C'est justement là que tu te trompes, et l'origine de tous tes problèmes...


                                                            Je ne parviens pas à saisir... je l'utilise, justement, donc je ne passe pas par tout le processus de conversion.

                                                            bacelar a écrit:

                                                            Votre code serveur SVP. (BIS)


                                                            Ci-joint le code serveur :

                                                            #include "EasySockets.hpp"
                                                            #include <fstream>
                                                            
                                                            int main(){
                                                            	Socket sock{TCP, "127.0.0.1", 19779, 1, 1500};						//construit la socket. elle écoutera sur l'adresse 127.0.0.1 sur le port 19779, et la taille de son buffer de réception sera de 1500 octets
                                                            	sock.ES_start();													//lance un bind et un listen sur la socket
                                                            
                                                            	std::string directory;
                                                            	std::string filename;
                                                            
                                                            	std::fstream file;
                                                            	char packet[1460];													//buffer du paquet à envoyer
                                                            	long packet_number;													//nombre de paquets à envoyer contenant chacun 1460 octets de données (sans prendre en compte les en-têtes IP et TCP)
                                                            	long last_packet_size;												//taille du dernier paquet à envoyer si la taille du fichier n'est pas un multiple de 1460
                                                            
                                                            	sock.ES_accept("client");											//accepte un nouveau client et l'enregistre sous le nom de "client"
                                                            
                                                            	sock.ES_recv("client");												//reçoit le chemin du répertoire du fichier à télécharger de la part du client et stocke ce chemin dans "directory"
                                                            	directory = sock.getBuffer();
                                                            
                                                            	sock.ES_recv("client");												//reçoit le nom du fichier à télécharger de la part du client et stocke ce nom dans "filename"
                                                            	filename = sock.getBuffer();
                                                            
                                                            	file.open(directory + filename, std::ios::in | std::ios::binary);
                                                            	file.seekg(0, std::ios::end);
                                                            	packet_number = file.tellg() / 1460;								// -|
                                                            	last_packet_size = file.tellg() % 1460;								//  | définit "packet_number", "last_packet_size", puis les envoie au client
                                                            	sock.ES_send("client", std::to_string(packet_number));				//  |
                                                            	sock.ES_send("client", std::to_string(last_packet_size));			// -|
                                                            
                                                            	file.seekg(0, std::ios::beg);
                                                            	for(long i(0) ; i < packet_number ; i++){							//boucle qui lit 1460 octets de données dans le fichier et les envoie au client
                                                            		file.read(packet, 1460);
                                                            		sock.ES_send("client", packet);
                                                            	}
                                                            	file.read(packet, last_packet_size);								//lecture et envoi au client des derniers octets du fichier
                                                            	sock.ES_send("client", packet);
                                                            
                                                            	file.close();
                                                            
                                                            	sock.ES_shutdown("client");											//déconnecte le client
                                                            	sock.ES_disconnect();												//ferme la socket
                                                            
                                                            	return 0;
                                                            }

                                                            L'en-tête "EasySockets.hpp" contient des fonctions dont je me sert pour utiliser les sockets de manière plus simple. Dans la plupart des cas, les noms de ces fonctions me semblent explicites, mais je précise quand même que ES_recv() stocke le contenu reçu dans le buffer de réception que l'on récupère à l'aide de la fonction getBuffer(), et que ES_start() lance un bind et un listen avec les paramètres enregistrés lors de la création de la socket.

                                                            -
                                                            Edité par Yixraie 20 février 2023 à 17:22:34

                                                            • Partager sur Facebook
                                                            • Partager sur Twitter
                                                              20 février 2023 à 22:34:50

                                                              J'ai l'impression que @koala01 a lu un peu trop vite la file de messages. ;-)

                                                              Vous ne nous donnez que très très peu de code effectif.

                                                              Mais du code que vous nous donnez, il me semble que la notion de flux de TCP et non de message UDP ne semble pas transparaître des lignes 19 et 22.

                                                              Vous êtes sûr pour le "in" en ligne 24 ?

                                                              On fait l'impasse sur la représentation des nombres qui peuvent changer d'une plateforme et configuration de plateforme à l'autre.(lignes 28 et 29)

                                                              >c'est-à-dire des "basic_istream", des  "char_traits" et autres noms dans ce goût là

                                                              Ca sent la sérialisation faite à l'arrache avec des 'to_string" sur nimpornawak. Mais on n'a pas le code pour le voir.

                                                              Bref vous êtes encore à des kilomètres de truc qui fait vaguement quelque-chose de pas fiable.

                                                              Pourquoi vous faire chier quand il existe des centaines de bibliothèques qui feront bien mieux que vous (et moi) ?

                                                              • Partager sur Facebook
                                                              • Partager sur Twitter
                                                              Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.

                                                              Envoi de fichiers de tout types en C++ via sockets

                                                              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                                              × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                                              • Editeur
                                                              • Markdown