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

Réseau C Discussion :

Fichiers binaires et sockets


Sujet :

Réseau C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    96
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 96
    Par défaut Fichiers binaires et sockets
    Bonjour,

    Je poste le sujet dans la section langage étant donné que mon problème actuel n'est pas un problème réseau.
    Je me suis renseigné sur la toile auparavant et voici les informations que j'ai regroupé :

    • Pour envoyer un fichier binaire, il faudrait apparemment retranscrire le contenu du fichier binaire en code ASCII pour ensuite l'envoyer.
    • Une autre solution serait de stocker dans un buffer de Bits chacun des bits contenus dans le fichier et d'envoyer ce buffer avec le cast qui va bien (?).


    Pourriez-vous confirmer ou infirmer ceci ?

    Je vais utiliser la méthode Read pour remplir mon buffer. Est-ce la méthode qui, généralement, est utilisée pour ce travail ?
    Si mon fichier a une taille supérieure à 2048 octets, dois-je prévoir un envoi séquencé ?

  2. #2
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 51
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Par défaut
    Citation Envoyé par theawe Voir le message
    Pour envoyer un fichier binaire, il faudrait apparemment retranscrire le contenu du fichier binaire en code ASCII pour ensuite l'envoyer.
    Première nouvelle... Les sockets binaires fonctionnent parfaitement bien, aucun problème à ce sujet, et ça t'évitera de doubler (au moins) la taille de ton envoi.

    Tu peux certes utiliser un codage type Base64 ou autre UUEncode afin de n'avoir que des caractères imprimables, mais cela n'est réellement utile que pour effectuer un transfert via un système ne gérant que le texte brut ASCII (32..127 + caractères de contrôle) comme peuvent l'être les protocoles Telnet, SMTP, NNTP, IRC, etc.

    Mais si c'est toi qui maîtrise les deux sockets source et destination, vas-y en binaire, ce sera bien plus rapide... Personnellement, je compresserais en plus les données à la volée avant de les expédier.

    Citation Envoyé par theawe Voir le message
    [*]Une autre solution serait de stocker dans un buffer de Bits chacun des bits contenus dans le fichier et d'envoyer ce buffer avec le cast qui va bien (?).
    ... Encore pire que du codage texte.

    Citation Envoyé par theawe Voir le message
    Je vais utiliser la méthode Read pour remplir mon buffer. Est-ce la méthode qui, généralement, est utilisée pour ce travail ?
    Si c'est depuis un fichier sur le disque, oui, c'est bien ça, il faut juste penser auparavant à ouvrir le fichier en mode binaire justement.

    Citation Envoyé par theawe Voir le message
    Si mon fichier a une taille supérieure à 2048 octets, dois-je prévoir un envoi séquencé ?
    En TCP/IP, tu n'as pas à te soucier de ça : tu lis par blocs (attention à la valeur de retour du nombre d'octets réellement lus depuis le fichier !!!!), tu balances tout directement dans la socket sans préavis, et tu t'arrêtes quand le nombre d'octets réellement lus est STRICTEMENT inférieur (peut être zéro également) au nombre d'octets demandés (2048 dans ton cas).

    Si tu fais de l'UDP, c'est plus complexe, car il n'y a pas de garantie de livraison des paquets. Il te faudra donc réimplémenter un tel mécanisme pour garantir la fiabilité des données.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  3. #3
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Par défaut
    Citation Envoyé par theawe Voir le message
    Pour envoyer un fichier binaire, il faudrait apparemment retranscrire le contenu du fichier binaire en code ASCII pour ensuite l'envoyer.
    Non, ce n'est pas obligatoire, tu peux transmettre du binaire. Par contre l'emetteur et le récepteur doivent s'entendre sur un minimum de protocole. En général, l'emetteur du fichier (binaire ou texte, cela n'a pas d'importance) commence par envoyer la taille du fichier et ensuite le fichier lui même. Comme cela, le récepteur commence par lire la taille du fichier et sait exactement le nombre d'octets qu'il doit recevoir.

    Citation Envoyé par theawe Voir le message
    Une autre solution serait de stocker dans un buffer de Bits chacun des bits contenus dans le fichier et d'envoyer ce buffer avec le cast qui va bien (?).
    C'est aussi une solution, c'est ce qui est fait pour envoyer du binaire sur un protocole texte (HTTP ou SMTP). Le binaire est alors transformé en texte avec un algo genre base64 ou mime.

    Citation Envoyé par theawe Voir le message
    Je vais utiliser la méthode Read pour remplir mon buffer. Est-ce la méthode qui, généralement, est utilisée pour ce travail ?
    De quel buffer parles tu ?

    Citation Envoyé par theawe Voir le message
    Si mon fichier a une taille supérieure à 2048 octets, dois-je prévoir un envoi séquencé ?
    Si tu es en TCP, tu n'a pas besoin de faire un envoi séquencé, tu peux envoyer en une seule fois 1MO ou plusieurs fois 2048 octets si tu veux. Par contre, le récepteur recevra ce MO en plusieurs fois (même dans le bon ordre, c'est garanti par TCP). D'où l'importance que le récepteur sache la taille à recevoir.

    En TCP, une émission peut correspondre à plusieurs réception et plusieurs émissions peuvent se traduire en une seule réception. Le nombre d'envois n'est pas forcément le nombre de réceptions

    [EDIT] Grillé mais même réponse, c'est rassurant !!
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  4. #4
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 51
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Par défaut
    Citation Envoyé par ram-0000 Voir le message
    [EDIT] Grillé mais même réponse, c'est rassurant !!
    D'un autre côté, sur ce coup, y'a qu'une seule "bonne" réponse, on risquait pas trop le début de troll !
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    96
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 96
    Par défaut
    En TCP je peux donc envoyer mon fichier en une seule fois ? Savoir combien d'octets il faut que je reçoive est important simplement pour contrôler la bonne réception du fichier ?


    @ram-0000 : Je parlais du buffer à envoyer. Si je procède comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    ifstream fichier;
    
    fichier.open("chemin", ios::out | ios::binary);
    /* ... calcul de la taille du fichier, (re)positionnement de l'offset ... */
    
    TYPE buffer = new TYPE[taille_fichier];
    
    fichier.read(buffer, taille_fichier);
    // J'ai un doute quant au second paramètre
    
    fichier.close();
    
    send(SocketClient, (cast ?)buffer, taille_fichier, 0);
    indépendamment des contrôles d'erreurs que je n'effectue pas en règle générale (c'est une ébauche), serait-ce le bon moyen ?

    Je ne connais pas le type du buffer à déclarer. Je me doute bien que je saute plusieurs étapes. Admettons que ce soit la bonne procédure, en travaillant comme ceci, pourrais-je envoyer et recevoir en une seule fois mon fichier ? (j'entends par là un seul appel des fonctions send() et recv())

    J'ai essayé quelques petites choses, sans succès. Je n'avais jamais utilisé les buffers avant cela.(En fait, je n'avais tout simplement pratiquement jamais touché au C++)

    J'ai essayé ceci.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    std::vector<unsigned char> all;
    unsigned char byte = '\0';
     
    while(fic.read((char *)&byte, sizeof(byte)))
    {
    	all.push_back(byte);
    }
     
    fic.close();
     
    for(int i = 0; i<(int)all.size(); i+= 2048)
    {
    	unsigned char monBuff[2048] = {0};
    	int bytesToCopy = 2048;
            if(i+2048 > (int)all.size()) bytesToCopy = all.size() - i;
    	memcpy(monBuff, &all[i], bytesToCopy);
    	send(socketRelais, (char*)buffer, bytesToCopy, 0);
    }
    C'est un code que j'avais trouvé ce matin, donc bof...
    Je n'ai pas réussi à le faire fonctionner de toute façon et n'ai pas cherché plus que ça à savoir pourquoi.

  6. #6
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Par défaut
    Citation Envoyé par theawe Voir le message
    j'entends par là un seul appel des fonctions send() et recv())
    Ne jamais penser que le nombre de send est égal au nombre de recv (cf mon post précédent)

    Ton pseudo code est chargé le fichier en mémoire juste avant de l'envoyer, si ce fichier fait 1K ou 2, pas de problèmes. Par contre, quel gachis si ton fichier fait quelques MO, allouer de la mémoire pour ensuite la liberer, c'est pas cool.

    Je te propose le pseudo code suivant

    Code Pseudo code emetteur : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    Lire la taille du fichier et stocker cette valeur dans TailleFichier
    Envoyer la taille du fichier
    Ouvrir le fichier en mode binaire et en lecture
    Nombre total d'octet lu = 0
    Tant que le nombre d'octets lu n'est pas égal à la taille du fichier
       Nombre partiel d'octet lu = Lire un bloc de données
       Envoyer le bloc de données lu de la taille du nombre partiel d'octets lus
       Nombre total d'octet lu = Nombre total d'octet lu + Nombre partiel d'octet lu
    Fin tant que
    Fermer le fichier


    Code Pseudo code recepteur : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    recevoir la taille du fichier et stocker cette valeur dans TailleFichier
    Ouvrir le fichier en mode binaire et en écriture
    Nombre total d'octet lu = 0
    Tant que le nombre d'octets lu n'est pas égal à la taille du fichier
       Nombre partiel d'octet lu = recevoir un bloc de données
       Ecrire dans le fichier le buffer recu
       Nombre total d'octet lu = Nombre total d'octet lu + Nombre partiel d'octet lu
    Fin tant que
    Fermer le fichier

    A compléter avec la gestion des erreurs
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  7. #7
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 51
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Par défaut
    Le type d'un buffer de ce genre, en général, c'est "unsigned char*".

    Il faut éviter de tenter la lecture complète du fichier d'un seul coup : s'il est trop gros, ça va crasher. En général, j'utilise une taille de fragmentation (= taille des lectures unitaires) de 64 ko pour ma part, 1024 ko si je sais par avance que je vais gérer forcément de très gros fichiers.

    Après, si tu ne cherches pas à savoir pourquoi ça ne fonctionne pas, ni à utiliser la "bonne" méthode, c'est un choix... Choix qui reste plus que discutable par contre.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  8. #8
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    96
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 96
    Par défaut
    Voilà, j'ai posé un peu tout ça et voici mon code :

    Côté Serveur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    fic.open(buff, ios::out | ios::binary);
    int nbTotalOctetLu = 0; int nbPartielOctetLu;
    while(nbTotalOctetLu < size)
    {
          if(size - nbTotalOctetLu >= 2048)
         {
    	   fic.read(monBuffer, 2048);
    	   nbTotalOctetLu = nbTotalOctetLu + send(socketRelais, (const char *)&monBuffer, 2048, 0);;
         }
         else
         {
    	   fic.read(monBuffer, size - nbTotalOctetLu);
    	   send(socketRelais, (char *)&monBuffer, size-nbTotalOctetLu, 0);
    								nbTotalOctetLu = size;
         }
     
    }
    fic.close();
    Côté Client :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    /* ... récupération de la taille du fichier par socket ... */
    ofstream fic;
    int nbOctetLu = 0; int nbPartielOctetLu;
    fic.open(ch, ios::in | ios::binary);
    while(nbOctetLu < tailleFichier)
    {
    	nbPartielOctetLu = recv(sock, monBuff, sizeof(monBuff), 0);
    	fic.write(monBuff, nbPartielOctetLu);
    	nbOctetLu = nbOctetLu + nbPartielOctetLu;
    }
    fic.close();
    J'ai un soucis majeur :
    Il concerne l'envoi du buffer par la socket. Je ne sais pas quel cast réaliser.

    Des suggestions ?

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Fichier binaire, string et sockets
    Par 10_GOTO_10 dans le forum Langage
    Réponses: 4
    Dernier message: 14/08/2010, 10h23
  2. [C#] Socket et fichier binaire
    Par NeoKript dans le forum C#
    Réponses: 1
    Dernier message: 08/12/2009, 23h06
  3. communication fichier binaire fichier txt
    Par micdie dans le forum C
    Réponses: 3
    Dernier message: 05/12/2002, 00h19
  4. transfert d'un fichier bitmap en socket tcp
    Par localhost dans le forum C++Builder
    Réponses: 5
    Dernier message: 29/07/2002, 00h40
  5. fichier binaire ou texte
    Par soussou dans le forum C++Builder
    Réponses: 4
    Dernier message: 14/06/2002, 13h39

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