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

Entrée/Sortie Java Discussion :

Socket et Transfert de fichiers


Sujet :

Entrée/Sortie Java

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2011
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2011
    Messages : 8
    Points : 8
    Points
    8
    Par défaut Socket et Transfert de fichiers
    Bonsoir à tous

    Je suis nouveau sur developpez.com, et si je post c'est vraiment parce que je suis bloqué de chez bloqué.

    La situation: J'ai fais un petit programme d'entrainement permettant le transfert de fichiers, aussi bien binaire que text, de toute manière ça n'a pas d'importance, je gère les fichier avec des flux binaire .

    Le problème, c'est que l'envoie de fichier trop volumineux nécessite l'envoie par packets! J'ai donc utilisé un buffer de 4096 bytes.
    Ainsi pas de problème, je parviens bien à transférer le fichier entre le client et le serveur mais, lorsque je reçois le fichier à l'arrivé, ce dernier est 8 fois sur 10 corrompu .

    En effet, son volume est supérieur au fichier original de quelque octets!

    Si vous pouvez m'aidez ce serai vraiment sympa:

    Précision sur le code: utilise uniquement la bibliothèque standard et swing pour le GUI, donc rapide si vous voulez tester pour m'aider .

    Le client: (ENVOIE DU FICHIER, ici nommé: "s.avi")
    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
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    import java.awt.BorderLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.io.BufferedInputStream;
    import java.io.BufferedOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.net.Socket;
    import java.net.UnknownHostException;
    import java.text.DecimalFormat;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JProgressBar;
     
     
    public class Foo extends JFrame{
     
     
    	private JProgressBar load;
    	private JButton launch;
    	private JLabel dl =new JLabel();
     
    	public static final int BUFFER_SIZE =4096;
     
     
    	public static void main(String args[]) throws InterruptedException{
    		//EXEC PROGRAMME
    		new Foo();
    	}
     
     
    	public Foo() throws InterruptedException{
    		//INIT GUI
    		this.setSize(400, 200);
    		this.setTitle("DownLoad File");
    		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		this.setLocationRelativeTo(null);
    		this.load =new JProgressBar();
    		this.load.setMaximum(100);
    		this.load.setMinimum(0);
    		this.load.setStringPainted(true);
    		this.getContentPane().add(this.load, BorderLayout.CENTER);
    		this.launch =new JButton("Send");
    		//LANCER TRANSFERT DU FICHIER(DANS UN THREAD) AU CLICK DU BUTTON
    		this.launch.addActionListener(new ActionListener(){
    			@Override
    			public void actionPerformed(ActionEvent e){
    				new Thread(new Traitement()).start();
    			}
    		});
    		this.getContentPane().add(launch, BorderLayout.SOUTH);
    		this.dl.setText("Téléchargé: ");
    		this.getContentPane().add(dl, BorderLayout.NORTH);
    		this.setVisible(true);
    	}
     
    	public class Traitement implements Runnable{
    		@Override
    		public void run(){
    			Foo.this.launch.setEnabled(false);
    			BufferedInputStream bis =null;
    			try{
    				//OUVERTURE EN LECTURE DU FICHIER @ ENVOYER
    				bis =new BufferedInputStream(
    						new FileInputStream(
    							new File("s.avi")));
    			//EXCEPTION NON GéRé
    			}catch(FileNotFoundException e){}
    			Socket sock;
    			try{
    				//INIT VARS
    				sock = new Socket("127.0.0.1", 22000);
    				//ECRIRE SUR LA SOCKET
    				BufferedOutputStream bos =new BufferedOutputStream(sock.getOutputStream());
     
    				DecimalFormat formater =new DecimalFormat("0.##");
    				byte buffer[] =new byte[Foo.BUFFER_SIZE];
    				float s, kodl;
    				int i =0;
    				Foo.this.load.setMaximum((int)(s =bis.available()));
    				s /=1000000;
    				long start =System.currentTimeMillis();
     
    				//ENVOIE DU FICHIER
    				while(bis.read(buffer) !=-1){
    					bos.write(buffer);
    					bos.flush();
    					i +=Foo.BUFFER_SIZE;
    					//AFFICHAGE GUI
    					Foo.this.load.setString(formater.format((float)i /1000000) +"/" +formater.format(s) +" Mo   vitesse de dl: " +formater.format(kodl =((float)i /1000 /((System.currentTimeMillis() -start) /1000))) +" Ko/s   Tps estimé: " +(int)((s *1000) /kodl) +" sec");
    					Foo.this.dl.setText("@Télécharger: " +formater.format((float)bis.available() /1000000) +" Mo           " +" En téléchargement depuis: " +(System.currentTimeMillis() -start) /1000 +" sec");
    					Foo.this.load.setValue(i);
    				}
    				//AFFICHAGE GUI
    				Foo.this.dl.setText("Téléchargé en: " +(System.currentTimeMillis() -start) /1000 +" sec");
    				Foo.this.load.setString("Téléchargement Terminé!");
    				//FERMETURE STREAM
    				bis.close();
    				bos.close();
    				sock.close();
    			//EXCEPTION NON GéRéeS
    			}catch (UnknownHostException e){
    			}catch (IOException e){}
    			System.out.println("FICHIER TRANSFERé");
    			Foo.this.launch.setEnabled(true);
    		}
     
    	}
     
    }

    Le serveur: (RéCEPTION du fichier "s.avi")

    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
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    import java.io.BufferedInputStream;
    import java.io.BufferedOutputStream;
    import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.RandomAccessFile;
    import java.net.ServerSocket;
    import java.net.Socket;
     
     
    public class Foo{
     
    	public static final int BUFFER_SIZE =4096;
     
    	public static void main(String argv[]) throws IOException{
    		//SERVEUR GERE UNIQUEMENT 1 CONNECTION A LA FOIS
    		//ACCEPTE UNE NOUVELLE CONNECTION A LA RECEPTION COMPLETE DU FICHIER
    		while(true){
    			System.out.println("Serveur lancé!");
    			ServerSocket ssock =new ServerSocket(22000, 1);
    			Socket csock =ssock.accept();
    			System.out.println("Une connexion entrante...\n\tRéception du fichier en cours...");
    			//LECTURE DU SOCKET
    			BufferedInputStream bis =new BufferedInputStream(csock.getInputStream());
     
    			//ECRITURE DANS LE NOUVEAU FICHIER
    			BufferedOutputStream bos =new BufferedOutputStream(
    									      new FileOutputStream(
    									          new File("s.avi")));
     
    			byte buf[] =new byte[Foo.BUFFER_SIZE];
    			//RéCEPTION DU FICHIER
    			while(bis.read(buf) !=-1){
    				bos.write(buf);
    				bos.flush();
    			}
    			//FERMETURE STREAM
    			bos.close();
    			bis.close();
    			ssock.close();
    			csock.close();
    			System.out.println("Fichier réceptionné !\n\n");
    		}
    	}
     
    }
    C'est donc lors de l'envoie: confer ligne commenté de mon code: "//ENVOIE DU FICHIER" et "//RéCEPTION DU FICHIER" que je dois oublier de faire un contrôle ou autres choses... Mais quoi ?

    Merci d'avance pour votre précieuse aide, car malgré mes nombreuses recherchse, je n'ai rien trouvé de fonctionnel, ou qui pourrai apporter de nouvelles pistes! Hormis sur un forum ou quelqu'un proposait de faire un accusé de réception afin de vérifier l'ordre de réception des données et leur intégrité, mais les protocoles TCP/IP s'occupent de gérer cela il me semble.
    De plus j'ai essayé avec la méthode available() de l'objet InputStream/BufferedInputStream pour boucler dessus mais le résultat est le même qu'avec la méthode read() utilisé ici dans l'exemple de mon code ci-dessus.

    PS: le code n'est pas optimisé: exceptions non gérées, etc..

  2. #2
    Modérateur
    Avatar de wax78
    Homme Profil pro
    Chef programmeur
    Inscrit en
    Août 2006
    Messages
    4 074
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Belgique

    Informations professionnelles :
    Activité : Chef programmeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2006
    Messages : 4 074
    Points : 7 978
    Points
    7 978
    Par défaut
    Au hasard, car je vais peut être dire une connerie, mais si jamais ton recepteur recois 3042 bytes car c'est la fin du fichier (au lieu des 4096 habituelles, taille de ton buffer que tu write juste apres en ecrivant 4096 bytes si je ne m'abuse...), le write il va ecrire 4096 bytes (taille du buffer).

    Ne faudrait-il pas écrire le nombre de byte réelement lu ?
    (Les "ça ne marche pas", même écrits sans faute(s), vous porteront discrédit ad vitam æternam et malheur pendant 7 ans)

    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  3. #3
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,



    @wax78 +1
    Et pas seulement à la fin du fichier... mais n'importe quand en fait (selon l'occupation réseau ou autre). Rien ne garantie que le read() va remplir le buffer. Il faut récupérer la valeur de retour :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    byte[] buffer = ...
    int len;
     
    while ( (len=input.read(buffer)) != -1) {
    	output.write(buffer, 0, len);
    }

    Sinon d'autres remarques :
    • Les exceptions non gérés c'est affreux !!! Si tu ne veux pas les gérer au moins englobes les dans une RuntimeException !
    • Utilises des try/finally pour chaque ressources à fermer.
    • Le BufferedOutputStream est inutile puisque tu fais déjà une copie par buffer...

  4. #4
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2011
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2011
    Messages : 8
    Points : 8
    Points
    8
    Par défaut
    D'accord merci beaucoup, pourtant j'avais essayé la méthode write(byte[], int, int) mais pas de la bonne façon surement.

    adiGuba => Oui je sais que je ne gère pas les exceptions, car c'est un code d'entrainement bidon, juste pour réussir un transfert de fichier sans perte de données.

    Dans tout les cas merci pour vos réponses, bonne soirée .

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

Discussions similaires

  1. Réponses: 17
    Dernier message: 15/05/2007, 18h35
  2. [reseaux] IO::Socket::Inet et transferts de fichiers
    Par jp_sympa dans le forum Programmation et administration système
    Réponses: 3
    Dernier message: 20/05/2005, 11h30
  3. Transfert de fichiers par sockets
    Par Kaori dans le forum C++
    Réponses: 19
    Dernier message: 26/01/2005, 13h58
  4. [Socket]Transfert de fichier
    Par Aminos dans le forum Entrée/Sortie
    Réponses: 4
    Dernier message: 19/04/2003, 13h58

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