Transfert de fichier

Soyez le premier à donner votre avis sur cette source.

Vue 13 028 fois - Téléchargée 1 642 fois

Description

Ce petit programme permet simplement de transférer un fichier entre deux machines.

Côté client; le programme lit un fichier par paquets (par défaut, les paquets sont de 32768 bits)
Le tableau de bytes est serializé (avec un BinaryFormatter) et envoyé dans la foulée via un objet NetworkStream.

Côté serveur; on déserialize le tableau de bytes venant du NetworkStream et on écrit le fichier au fur et à mesure des paquets reçus.

Petit bonus : Avant l'envoi du fichier, le client envoi un objet FileTransfer pour indiquer au serveur le nom et la taille (en octets) du fichier

Dans le zip, il y aussi une vérification de l'intégrité du fichier avec un hash sha1

Pour l'utiliser, lancer l'exécutable sur deux machines;
- Sur l'un utilisez le mode serveur, sur le second le mode client
- le client doit indiquer l'ip du serveur
- l'utilisateur du client indique le nom du fichier
- le fichier est transféré

Source / Exemple :


using System;
using System.Net.Sockets;
using System.Net;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Security.Cryptography;

namespace FileTransfer
{
    class Program
    {
        static void Main()
        {

            Console.Write("Mode client ou serveur ? (C/S) : ");
            string mode = Console.ReadLine().ToUpper();

            Int64 buffersize = 32768;
            DateTime dt_debut;

            if (mode == "C")
            {
                //Connexion
                Console.Write("ip serv : ");

                TcpClient tc = new TcpClient();
                tc.Connect(new IPEndPoint(IPAddress.Parse(Console.ReadLine()), 1337));
                NetworkStream ns = tc.GetStream();

                Console.WriteLine("serveur connecté");
                Console.Write("filename : ");
                String filename = Console.ReadLine();

                
                //Send File infos
                BinaryFormatter bf = new BinaryFormatter();

                String filehash = FileHash(filename);
                Int64 filesize = new FileInfo(filename).Length;
                FileTransfer ft = new FileTransfer(filename, filesize, filehash);

                bf.Serialize(ns, ft);
                dt_debut = DateTime.Now;

                //ok, read/send the file
                FileStream fs = new FileStream(filename, FileMode.Open);
                Int64 bytesOk = 0;

                while (bytesOk < filesize)
                {
                    if (filesize - bytesOk < buffersize)
                        buffersize = filesize - bytesOk;

                    Byte[] buffer = new Byte[buffersize];
                    fs.Read(buffer, 0, (int)buffersize);
                    bf.Serialize(ns, buffer);

                    bytesOk += buffersize;

                    Console.Write("\rSent : " + Math.Round((double)bytesOk / filesize * 100) + "%");
                }

                Console.WriteLine("\r\nfichier envoyé");

                ft = (FileTransfer)bf.Deserialize(ns);
                Console.WriteLine((ft.hash == filehash) ? "fichier bien recu" : "erreur lors du transfert");

                //Close ALL the object\r\n
                fs.Close();
                ns.Close();
                tc.Close();
            }
            else
            {
                Console.WriteLine("En attente du client");

                //Attente d'un client
                TcpListener tl = new TcpListener(new IPEndPoint(IPAddress.Any, 1337));
                tl.Start();
                TcpClient tc = tl.AcceptTcpClient();
                tl.Stop();
                NetworkStream ns = tc.GetStream();

                Console.WriteLine("Client connecté");
                

                //Receive File infos
                BinaryFormatter bf = new BinaryFormatter();
                FileTransfer ft = (FileTransfer)bf.Deserialize(ns);

                Console.WriteLine(ft.name + " - " + ft.size);
                Int64 filesize = ft.size;
                String filename = ft.name;
                String filehash = ft.hash;
                dt_debut = DateTime.Now;

                //ok, receive/write the file
                FileStream fs = new FileStream(filename, FileMode.Create);
                Int64 bytesOk = 0;

                while (bytesOk < filesize)
                {
                    Byte[] buffer = (Byte[])bf.Deserialize(ns);
                    buffersize = buffer.Length;
                    fs.Write(buffer, 0, (int)buffersize);
                    bytesOk += buffersize;

                    Console.Write("\rReceived : " + Math.Round((double)bytesOk / filesize * 100) + "%");
                }

                Console.WriteLine("\r\nfichier écrit");
                Console.WriteLine((ft.hash == filehash) ? "fichier bien recu" : "erreur lors du transfert");

                bf.Serialize(ns, new FileTransfer("", 0, filehash));

                //Close ALL the object\r\n
                fs.Close();
                ns.Close();
                tc.Close();
            }

            TimeSpan ts = DateTime.Now - dt_debut;
            Console.WriteLine("Temps total : " + (ts.Minutes + "m " + ts.Seconds + "s " + ts.Milliseconds + "ms"));

            Console.Read();
        }

        static String FileHash(String filename)
        {
            SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();
            byte[] buffer;

            using (FileStream fs = File.Open(filename, FileMode.Open, FileAccess.Read))
                buffer = sha1.ComputeHash(fs);

            return BitConverter.ToString(buffer).Replace("-", String.Empty);
        }
    }

    [Serializable]
    public class FileTransfer
    {
        public String name;
        public Int64 size;
        public String hash;

        public FileTransfer(String name, Int64 size, String hash)
        {
            this.name = name;
            this.size = size;
            this.hash = hash;
        }
    }
}

Codes Sources

A voir également

Ajouter un commentaire

Commentaires

il marche pas j ai eu une erreur c'est The specified path is invalid
svp aide moi :/
j'ai essayé avec des fichiers PDF 2.5 MO il me donne des fichiers PDF reçus endommagés
Utilisateur anonyme
Vraiment merci pour ton exemple, tu m'as fais découvrir la "déserialization" d'objets :).

Sorpia.
Messages postés
234
Date d'inscription
jeudi 18 janvier 2007
Statut
Membre
Dernière intervention
3 novembre 2011
1
Concernant l’intégrité des données, un contrôle MD5 est a priori superficiel. Le protocole TCP/IP inclut automatiquement un checksum dans l'en-tête de tous les paquets échangés. Il garantit donc que le fichier ne sera pas corrompu à son arrivée ;)

http://www.misfu.com/introduction-tcpip.html

Simon
Messages postés
3
Date d'inscription
mardi 25 novembre 2008
Statut
Membre
Dernière intervention
24 juillet 2009

Salut VinceMonkeyz,

Je t'invite à voir ce projet : http://www.codeproject.com/KB/files/fastbinaryfileinput.aspx

Cordialement,
Afficher les 9 commentaires

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.