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éception fichier Socket


Sujet :

C#

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2012
    Messages
    44
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gard (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : Novembre 2012
    Messages : 44
    Points : 36
    Points
    36
    Par défaut Réception fichier Socket
    Bonjour,

    Je développe une petite dll qui me permet de gérer la com' TCP, et cherche a y implémenter une fonction d'envoi de fichiers.

    Je cherche à éviter le File.ReadAllBytes() qui fait automatiquement grimper mon application à 500 Mo d'utilisation de mémoire vive dès que je veux envoyer un fichier de 100 Mo.

    J'ai donc réfléchis et cherche à envoyer un fichier par chunk de 1024 bytes, voici le code d'envoi :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    byte[] bufferFichier = new byte[1024];
    FileStream fs = File.OpenRead(ofd.FileName);
                    int bytesLus;
                    while ((bytesLus= fs.Read(bufferFichier, 0, bufferFichier.Length)) > 0) {
                        client.BeginSend(bufferFichier, 0, bufferFichier.Length, SocketFlags.None, new AsyncCallback(SendCallback), client);
                    }
    De ce coté-là à priori tout marche sans problème.

    En revanche je bloque du coté de la réception :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    private readonly object lockFichier = new object();
            private void ReceiveCallback(IAsyncResult ar) {
                Console.WriteLine("Réception données");
                Socket serveur = ar.AsyncState as Socket;
                int dataClient = serveur.EndReceive(ar);
                FileStream fs = new FileStream(@"salut.exe", FileMode.Append);
                lock (lockFichier) {
                    fs.Write(buffer, 0, dataClient);
                    fs.Close();
                    serveur.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), serveur);
                }
            }
    Je reçois entre 4 Mo et 12 Mo, variable, et puis bim, exception fichier en cours d'utilisation.

    Du coup je cherche à comprendre comment éviter ça, j'aimerai éviter de faire un Thread.Sleep(500) par exemple dans ma boucle while de la méthode d'envoi. Voir s'il y a une autre méthode qui puisse directement être implémenté dans la méthode de réception.

    Peut être que je comprends mal l'utilisation du lock ...

    Merci par avance.

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749
    Par défaut
    Tu te compliques vraiment la vie en utilisant directement un Socket... utilise plutôt TcpClient, c'est beaucoup plus pratique. Avec TcpClient tu peux obtenir un Stream, qui permet de gérer facilement la copie : avec la méthode CopyTo, tu peux copier du flux fichier au flux réseau, et inversement, sans avoir à te prendre la tête.

  3. #3
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2012
    Messages
    44
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gard (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : Novembre 2012
    Messages : 44
    Points : 36
    Points
    36
    Par défaut
    Je voudrai bien sauf qu'une très très grosse partie de ma dll est terminée et j'utilise déjà les fonction de base à travers diverses application ... Pas très envie de repasser de partout.

    Puis mon problème peut aussi arriver dans une autre utilisation que les sockets, du coup ça m'intéresserai de savoir comment pallier à ce problème d'écriture.

  4. #4
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749
    Par défaut
    En fait je m'aperçois que tu peux quand même utiliser un Stream avec un Socket : le constructeur de la classe NetworkStream prend le socket en paramètre.

    Donc pour recevoir un fichier, il suffit de faire ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    using (var networkStream = new NetworkStream(socket, false))
    using (var fileStream = File.OpenWrite(@"C:\test.txt"))
    {
        networkStream.CopyTo(fileStream);
    }
    et pour envoyer, c'est le contraire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    using (var networkStream = new NetworkStream(socket, false))
    using (var fileStream = File.OpenRead(@"C:\test.txt"))
    {
        fileStream.CopyTo(networkStream);
    }

  5. #5
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2012
    Messages
    44
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gard (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : Novembre 2012
    Messages : 44
    Points : 36
    Points
    36
    Par défaut
    Arf FileStream.CopyTo c'est au framework 4.

    J'ai essayé d'utiliser ça en passant au framework 4 mais les fichiers que je reçois ont l'air corrompu.

    Je vais essayer de chercher un peu.

  6. #6
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749
    Par défaut
    Citation Envoyé par Ywnith Voir le message
    Arf FileStream.CopyTo c'est au framework 4.
    Ca pose un problème ? le framework 4 c'est 2010 quand même... 3 ans, c'est une éternité dans le domaine de l'informatique

    Mais de toutes façons cette méthode est assez bidon, tu peux très bien la refaire sous forme de méthode d'extension :

    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
    20
    21
    22
    public class StreamExtensions
    {
        public static void CopyTo(this Stream source, Stream destination, int bufferSize = 0x14000)
        {
            if (destination == null)
                throw new ArgumentNullException("destination");
            if (!source.CanRead && !source.CanWrite)
                throw new ObjectDisposedException("source", "The source stream is closed");
            if (!destination.CanRead && !destination.CanWrite)
                throw new ObjectDisposedException("destination", "The destination stream is closed");
            if (!source.CanRead)
                throw new NotSupportedException("The source stream cannot be read");
            if (!destination.CanWrite)
                throw new NotSupportedException("The destination stream cannot be written");
            int count;
            byte[] buffer = new byte[bufferSize];
            while ((count = source.Read(buffer, 0, buffer.Length)) != 0)
            {
                destination.Write(buffer, 0, count);
            }
        }
    }

  7. #7
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2012
    Messages
    44
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gard (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : Novembre 2012
    Messages : 44
    Points : 36
    Points
    36
    Par défaut
    Yep j'ai fait cette fonction pendant ce temps, merci.

    Je cherche actuellement le fait que mes fichiers soient corrompus à l'arrivée, un fichier de 16 050 ko par exemple arriveras à 16 048 ko ou 047 ...

    Si je trouve le problème je posterai au cas où ça peut aider.

  8. #8
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749
    Par défaut
    Citation Envoyé par Ywnith Voir le message
    Yep j'ai fait cette fonction pendant ce temps, merci.

    Je cherche actuellement le fait que mes fichiers soient corrompus à l'arrivée, un fichier de 16 050 ko par exemple arriveras à 16 048 ko ou 047 ...

    Si je trouve le problème je posterai au cas où ça peut aider.
    Tu peux poster le code de ta fonction ? Celle que j'ai postée est quasiment la même que celle de .NET 4, vu que j'ai décompilé avec Reflector

  9. #9
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2012
    Messages
    44
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gard (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : Novembre 2012
    Messages : 44
    Points : 36
    Points
    36
    Par défaut
    Voilà la fonction pour envoyer :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    private void btnFichier_Click(object sender, EventArgs e) {
                OpenFileDialog ofd = new OpenFileDialog();
                ofd.Filter = "Tout les fichiers (*.*)|*.*";
                if (ofd.ShowDialog() == DialogResult.OK) {
                    using (var networkStream = new NetworkStream(client, false))
                    using (var fileStream = File.OpenRead(ofd.FileName)) {
                        fileStream.CopyTo(networkStream, 1024);
                    }
                }
            }
    Et lorsque je reçois :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    private void ReceiveCallback(IAsyncResult ar) {
                Console.WriteLine("Réception données");
                Socket serveur = ar.AsyncState as Socket;
                int dataClient = serveur.EndReceive(ar);
                using (var networkStream = new NetworkStream(serveur, false))
                using (var fileStream = File.OpenWrite(@"C:\test.rar")) {
                    networkStream.CopyTo(fileStream);
                }
     
            }
    J'ai essayé avec des Close() à tout hasard, sait-on jamais, mais pareil.

    Ca doit être une erreur bête je sens.

  10. #10
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749
    Par défaut
    OK, mais l'implémentation de CopyTo que tu utilises, c'est celle que je t'ai donnée ? ou celle de .NET 4 ?

    Je vois pas très bien ce qui peut expliquer le problème...

    Citation Envoyé par Ywnith Voir le message
    J'ai essayé avec des Close() à tout hasard, sait-on jamais, mais pareil.
    Pas la peine, les streams sont automatiquement fermés à la fin du bloc using

  11. #11
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2012
    Messages
    44
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gard (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : Novembre 2012
    Messages : 44
    Points : 36
    Points
    36
    Par défaut
    J'utilise celle de .NET 4, j'ai changé le Framework cible le temps de voir un peu ce que ça donnait, j'ai également essayé avec la méthode et pareil ...

    Je suis d'accord pour les streams je savais pour le using, j'avis essayé ça au 'cas où' incompréhensible.

    J'ai google ce soucis avec quelques mots-clefs du type "corrupt file networkstream" mais rien ...

  12. #12
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749
    Par défaut
    Bah écoute là je vois pas trop à quoi c'est dû... essaie de regarder ce qui est transmis avec Wireshark, ça te donnera peut-être l'explication.

  13. #13
    Membre expérimenté

    Homme Profil pro
    Responsable des études
    Inscrit en
    Mars 2009
    Messages
    553
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Responsable des études
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2009
    Messages : 553
    Points : 1 672
    Points
    1 672
    Par défaut
    Hello,
    16 050 ko, c'est la taille réelle du fichier ou bien la place occupée sur le disque ? Avec windows on se trompe facilement...

  14. #14
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2012
    Messages
    44
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gard (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : Novembre 2012
    Messages : 44
    Points : 36
    Points
    36
    Par défaut
    Citation Envoyé par nnovic Voir le message
    Hello,
    16 050 ko, c'est la taille réelle du fichier ou bien la place occupée sur le disque ? Avec windows on se trompe facilement...
    Je compare celui avec la colonne taille.

    j'ai essayé avec de nombreux fichiers, .exe, rar ... Tous corrompus.

  15. #15
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749
    Par défaut
    La seule explication que je vois, c'est que tu as déjà "consommé" une partie des données envoyées par le serveur avant de commencer à les copier dans le fichier. Mais c'est difficile de dire précisément ce qui cause ça sans savoir ce que fait le reste du code...

Discussions similaires

  1. RS232 réception fichier protocole XModem
    Par jerem59300 dans le forum C
    Réponses: 2
    Dernier message: 15/05/2015, 09h42
  2. configuration du fichier socket?
    Par usama2 dans le forum MySQL
    Réponses: 1
    Dernier message: 24/09/2008, 07h56
  3. Problème de réception dans Socket.
    Par rzayani dans le forum C++
    Réponses: 0
    Dernier message: 29/04/2008, 15h49
  4. suppression d'un fichier socket
    Par sofiane80 dans le forum Linux
    Réponses: 5
    Dernier message: 13/01/2008, 17h54
  5. fichiers sockets
    Par KeKiDiBiBa dans le forum C++
    Réponses: 4
    Dernier message: 09/01/2006, 19h34

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