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#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre actif
    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
    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 : 43
    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
    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
    Membre actif
    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
    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 : 43
    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
    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
    Membre actif
    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
    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 : 43
    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
    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);
            }
        }
    }

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