envoi de gros fichier par socket

envoi de gros fichier par socket - Java - Programmation

Marsh Posté le 04-05-2011 à 10:47:18    


bonjour,
 
je dois faire du transfert de fichiers assez volumineux par socket, mais je bloque un peu...
 
j'utilise un tampon pour decouper mon fichier, j'arrive bien a le transferer mais le client n'arrive pas à voir quand est ce que la fin du fichier arrive..
 
voici la code coté serveur (qui envoie le fichier) :

Code :
  1. File f = new File(pathname);
  2. System.out.println("Envoi du fichier " + f.getName());
  3. long taillefichier =f.length();
  4. System.out.println("Taille : "+ taillefichier);
  5. long nbpassagesuposé=taillefichier / 8192;
  6. System.out.println("Passages supposés : "+nbpassagesuposé);
  7. InputStream in = new BufferedInputStream(new FileInputStream(f));
  8. ByteArrayOutputStream tableaubytes = new ByteArrayOutputStream();
  9. BufferedOutputStream tampon = new BufferedOutputStream(tableaubytes);
  10. int lu = in.read();
  11. int[] aecrire = new int[8192];
  12. int compteur = 0;
  13. long ouonestrendu=0;
  14. //Tant qu'on est pas à la fin fichier
  15. while(lu > -1){
  16. //On lit les données du fichier
  17. aecrire[compteur] = lu;
  18. lu = in.read();
  19. compteur++;
  20. //Quand on a rempli le tableau, on envoie un paquet de 8192 octets
  21. if(compteur == 8192){
  22.  compteur=0;
  23.  ouonestrendu++;
  24.  //On remplit le tampon
  25.  for(int x=0;x<8192;x++)
  26.  tampon.write(aecrire[x]);
  27.  //Et on l'envoie
  28.  fluxsortie.write(tableaubytes.toByteArray());
  29.  tableaubytes.reset();
  30.  System.out.println("Avancement : "+(float) ouonestrendu/nbpassagesuposé * 100+"%" );
  31. }
  32. }
  33. //On envoie le dernier paquet, qui ne fait pas forcément 4096 octets
  34. //On remplit le tampon
  35. for(int x=0;x<compteur;x++)
  36. tampon.write(aecrire[x]);
  37. //Et on l'envoie
  38. tampon.flush();
  39. fluxsortie.write(tableaubytes.toByteArray());
  40. fluxsortie.flush();
  41. System.out.println("Avancement: "+(float) ouonestrendu/nbpassagesuposé * 100+"%" );
  42. System.out.println("fini" );
  43. in.close();
  44. tampon.close();
  45. System.out.println("Passages effectués : "+ouonestrendu);


 
 
voici le client qui recoit :
 

Code :
  1. Byte[] taillefichier;
  2. int lu;
  3. long taille = 0;
  4. //Création de l'entrée
  5. InputStream inpute = socket.getInputStream();
  6. OutputStream out = new FileOutputStream("/home/ginko/" + nomVideo);
  7. //Reçoit du client
  8. BufferedInputStream inBuffer = new BufferedInputStream(inpute);
  9. //Envoi vers le fichier
  10. BufferedOutputStream outBuffer = new BufferedOutputStream(out);
  11. lu = 0;
  12. int compteur = 0;
  13. while(lu > -1){
  14. lu = inBuffer.read();
  15. outBuffer.write(lu);
  16. compteur++;
  17. }
  18. outBuffer.flush();
  19. outBuffer.close();
  20. inBuffer.close();
  21. out.flush();
  22. out.close();
  23. inpute.close();
  24. System.out.println("fini" );


 
 
j'ai bien le transfert de fichier qui s'effectue, mais il ne s'arrete pas...  
 
si quelqu'un a deja fait qqch de similaire et peut me preter main forte..  
 
merci d'avance

Reply

Marsh Posté le 04-05-2011 à 10:47:18   

Reply

Marsh Posté le 04-05-2011 à 12:38:35    

C'est quoi la valeur de "lu" côté client?

 

Sinon tu fermes pas ton fluxsortie par un fluxsortie.close().


Message édité par gelatine_velue le 04-05-2011 à 12:41:43
Reply

Marsh Posté le 04-05-2011 à 13:35:46    

la valeur de lu ne passe jamais à -1...
 
elle ne voit pas la fin du fichier.. donc je ne peux pas l'arrêter.
 
pour ça, j'ai trouvé une solution, je créé un message avec la taille du fichier a envoyer :

Code :
  1. long taille =listeVideos.get(y).getFichierVideo().length();

 
 
puis je l'envoie via un message socket et j'ajoute ceci :
 

Code :
  1. while(lu > -1){
  2. lu = inBuffer.read();
  3. outBuffer.write(lu);
  4. compteur++;
  5. if (compteur == taille){
  6.  lu = -1;
  7. }
  8. }


 
grâce à ça, je peux arrêter la lecture du buffer et fermer mes flux.
 
mais je suis toujours pas sorti d'affaire, parce que je dois envoyer plusieurs fichiers a la suite,  
 
j'avais donc fais une procédure de ce genre :
 
- le serveur compte le nombre de fichier a envoyer et l'envoie au client
- le serveur fait une boucle de 0 a nombre de fichiers
      - envoie le nom et la taille du fichier
      - envoie le fichier
 
le client :
- le client reçoit le nombre de fichier
- le client fait une boucle de 0 a nombre de fichiers
      - reçoit le nom et la taille du fichier    
      - reçoit le fichier
 
cette procedure me semble correcte, elle marche bien pour le premier fichier, mais ca plante des le 2eme... avec un message connection reset..
 
c'est pour ca que je ne fermait pas le flux outputstream coté serveur, car je veux envoyer plusieurs fichiers..
 
 
 
Voici le code de la procedure ci dessus :
 

Code :
  1. int nbVideos = listeVideos.size();  /* nombre de videos a envoyer */
  2. reponseRequete = Proprietes.ACK + Proprietes.SEPARATOR + nbVideos;
  3. int ret = envoiMessage(reponseRequete);  /* envoi le message contenant le nombre de video */
  4. if (ret == Proprietes.ACK){                     /* l'envoi s'est bien passé */
  5. for (int y=0 ; y<nbVideos ; y++){           /* on liste toutes les videos à rapatrier  */
  6.  String nomVideo = listeVideos.get(y).getFichierVideo().getName();  /* recuperation du nom de fichier    */
  7.  long taillefichier =listeVideos.get(y).getFichierVideo().length();
  8.  String chemin = listeVideos.get(y).getFichierVideo().getAbsolutePath();
  9.  reponseRequete = Proprietes.ACK +  Proprietes.SEPARATOR + nomVideo+ Proprietes.SEPARATOR + taillefichier; /* on envoie nom et taille de la video  */
  10.  retour = envoiMessage(reponseRequete);   /* on envoie le message de la video au client  */
  11.  if (retour == Proprietes.ACK){     /* le client a bien recu le nom et la taille */
  12.   try {
  13.    retour = sendFile(chemin);  /* la fonction d'envoi deja postée */
  14.   } catch (IOException e) {
  15.    e.printStackTrace();
  16.   }
  17.  }else{
  18.   return Proprietes.ERR_UNKNOWN;
  19.  }
  20. }
  21. }


 
 
coté client :
 

Code :
  1. requete = recevoirMessage();             /* on recoit le nombre de videos */
  2. String[] stringSplit = requete.split(SEPARATOR); /* on split le nom de la video courante       */
  3. String codeRetourStr = stringSplit[0];
  4. int codeRetour = Integer.valueOf(codeRetourStr);
  5. if (codeRetour ==ACK){        /* il n'y a pas eu d'erreur detectee       */
  6. String nbVideoStr = stringSplit[1];    /* on recupere le nombre de videos sous forme de chaine   */
  7. int nbVideo = Integer.valueOf(nbVideoStr);  /* on le converti en entier          */
  8. for(int y = 0 ; y<nbVideo ; y++){    /* on boucle pour recuperer toutes les videos     */
  9.  requete = recevoirMessage();    /* recuperation de la requete du client      */
  10.  stringSplit = requete.split(SEPARATOR);  /* on split la requete          */
  11.  codeRetourStr = stringSplit[0];
  12.  codeRetour = Integer.valueOf(codeRetourStr);
  13.  String nomVideo = stringSplit[1];   /* on recupere le nom de la video sous forme de chaine  */
  14.  int nbEtapes =  Integer.valueOf(stringSplit[2]);
  15.  try {
  16.   ret = recuperationVideos(nomVideo, nbEtapes);  /* on lance la recuperation de la video, fonction deja postée tout au dessus     */
  17.  } catch (Exception e) {
  18.   e.printStackTrace();
  19.  }
  20. }
  21. }


 
l'erreur que j'obtiens
coté serveur :
java.net.SocketException: Broken pipe
 
coté client :
java.net.SocketException: Socket closed
 
 
si je vire les appels de fonctions qui envoient/recoivent les fichiers, tous les echanges fonctionnent, je dois donc fermer qqch qui bloque la connexion, puisque la ligne qui pose probleme, c'est celle contenant le writeObject(message); ou le readObject();
 
 
voila, j'espere avoir été clair.
 
 
merci pour votre aide !


Message édité par dumoulex le 04-05-2011 à 13:49:22
Reply

Marsh Posté le 04-05-2011 à 14:14:50    

C'EST BON !
 
je ne comprend pas vraiment pourquoi, (j'ai pas trouvé tout seul) mais si je ferme le  
BufferedInputStream inBuffer = new BufferedInputStream(socket.getInputStream());
 
et bien ca plante...

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed