Envoi des fichiers par des sockets java

Résolu
tissouassoum -  
KX Messages postés 16761 Date d'inscription   Statut Modérateur Dernière intervention   -
salut, pour mon projet je dois implémenter une application web qui servira à l'envoi des images et du sons, pour cela j'ai utilisé les sockets en JAVA j'ai mes codes qui marchent parfaitement coté serveur et coté client, je fais le RUN tout se passe bien et mon fichier, une fois reçue par mon serveur il est bien créé mais quand je le consulte je ne le trouve pas en totalité ( pour le son seulement quelques secondes sont jouées et parfois non executable, pour l'image, elle ne s'affiche pas il n'y a q'un croix rouge ) veuillez m'aider S.V.P et merci
et voila mes codes :
Côté Client:
public class Client {

public static void main(String[] zero) throws IOException {

File f = new File("C:\\Users\\Douda\\Downloads\\musicmp4.MP4");
if(f.exists())
{
System.out.println("Envoi du fichier "+f.toURI().toURL());
Socket s = new Socket(InetAddress.getLocalHost(),9001);

OutputStream fluxsortie = s.getOutputStream();

long taillefichier =f.length();

System.out.println("Taille : "+ taillefichier);

long nbpassagesuposé=taillefichier / 4096;

System.out.println("Passages supposés : "+nbpassagesuposé);

InputStream in = new BufferedInputStream(new FileInputStream(f));
ByteArrayOutputStream tableaubytes = new ByteArrayOutputStream();
BufferedOutputStream tampon = new BufferedOutputStream(tableaubytes);

int lu = in.read();
int[] aecrire = new int[4096];
int compteur = 0;
long ouonestrendu=0;

//Tant qu'on est pas à la fin du fichier
while(lu > -1)
{
//On lit les données du fichier
aecrire[compteur] = lu;
lu = in.read();
compteur++;


//Quand on a rempli le tableau, on envoie un paquet de 4096 octets
if(compteur == 4096)
{
compteur=0;
ouonestrendu++;
//On remplit le tampon
for(int x=0;x<4096;x++)
tampon.write(aecrire[x]);

//Et on l'envoie
byte[] b=tableaubytes.toByteArray();
tampon.write(b);
tampon.flush();

tableaubytes.reset();
System.out.println("Avancement : "+(float) ouonestrendu/nbpassagesuposé * 100+"%");
}
}

//On envoie le dernier paquet, qui ne fait pas forcément 4096 octets
//On remplit le tampon
for(int x=0;x<compteur;x++)
tampon.write(aecrire[x]);

//Et on l'envoie
tampon.flush();
fluxsortie.write(tableaubytes.toByteArray());
fluxsortie.flush();

System.out.println("Avancement: "+(float) ouonestrendu/nbpassagesuposé * 100+"%");

System.out.println("Youpi finished");
in.close();
tampon.close();
System.out.println("Passages effectués : "+ouonestrendu);
s.close();
}
else
{
System.out.println("Le fichier "+f+" est introuvable");
}

}

}
-----------------------------
*****************************
Coté Serveur:

public class Serveur {

public static void main(String[] zero) throws IOException {


//On attend la connexion d'un client
ServerSocket socketserver= new ServerSocket(9001);
Socket serviceSocket = socketserver.accept();


int lu;


//Création de l'entrée
InputStream inpute = serviceSocket.getInputStream();

OutputStream out = new FileOutputStream("C:\\musicmp4.MP4");

//Reçoit du client
BufferedInputStream inBuffer = new BufferedInputStream(inpute);

//Envoi vers le fichier
BufferedOutputStream outBuffer = new BufferedOutputStream(out);

lu = inBuffer.read();

int compteur = 0;

while(lu > -1)
{
outBuffer.write(lu);
lu = inBuffer.read();

compteur++;
}

outBuffer.write(lu);

outBuffer.flush();
outBuffer.close();
inBuffer.close();

out.flush();
out.close();
inpute.close();
serviceSocket.close();

}
}





<config,g>Windows 7 / Safari 535.1</config>
A voir également:

6 réponses

KX Messages postés 16761 Date d'inscription   Statut Modérateur Dernière intervention   3 020
 
Bon j'ai regardé ton code, le moins qu'on puisse dire c'est que tu te compliques la vie !
En particulier, pourquoi as-tu besoin d'ouvrir autant de flux ?

Voici le coeur du programme, tu vas voir qu'en fait c'est très simple !

public class Commun
{
    public static void transfert(InputStream in, OutputStream out, boolean closeOnExit) throws IOException
    {
        byte buf[] = new byte[1024];
        
        int n;
        while((n=in.read(buf))!=-1)
            out.write(buf,0,n);
        
        if (closeOnExit)
        {
            in.close();
            out.close();
        }
    }
}

public class Client
{
    public static void main(String...args) throws IOException 
    { 
        Socket sock = new Socket(InetAddress.getLocalHost(),9001);
    
        Commun.transfert(
                new FileInputStream("D:\\test.jpg"),
                sock.getOutputStream(),
                true);
        
        sock.close();
    } 
}

public class Serveur
{
    public static void main(String...args) throws IOException 
    { 
        Socket sock = new ServerSocket(9001).accept();
        
        Commun.transfert(
                sock.getInputStream(),
                new FileOutputStream("D:\\test2.jpg"),
                true);
        
        sock.close(); 
    } 
}
28
tissouassoum
 
merciiiiiiiiiiiiiiiiiiiiiiiiiiiii c'est trop mignon, court, et bien développé, et ça marche parfaitement :)
merci
0
Diouf
 
Mais moi je le lane comment ceci?
Et puis, drvrai-je mettre chaque classe ainsi décrite dans un fichier .java séparément?
0
KX Messages postés 16761 Date d'inscription   Statut Modérateur Dernière intervention   3 020
 
Oui chaque classe dans un fichier .java séparé, et après tu lances la classe serveur puis la classe client dans deux fenêtres distinctes.
0
Fallentree Messages postés 2309 Date d'inscription   Statut Membre Dernière intervention   209
 
t es sur qu il faut pas passer tes buffers en hexa ???
Et ta boucle d'arret doit se faire avec un code d'echappement, si mes souvenirs sont bon.
Par exemple un buffer d'une certaine taille avec des carracteres a la manque dedans ...
tu peux aussi rajouter un correcteur d erreur sur ta trame comme une somme que tu envoies soit à la fin soit comme nouvelle trame ...
Differents modèles de protocoles te permettent de jongler sur ces echanges ...
par exemple, renvoie de la trame si elle est fausse ou intercepté ...
0
Bob573
 
ce sujet date, juste pour ajouter pour ceux qui cherchent:

La fonction transfert bug parfois en fonction des extensions, et la boucle ne donne jamais comme résultat -1... mieux vaut utiliser:

public static void transfert(InputStream in, OutputStream out, boolean closeOnExit) throws IOException {
        byte buf[] = new byte[1024];
        
        int n;
        while((n=in.read(buf))==1024){
            out.write(buf,0,n);
        }
        //et la on ajoute les bytes plus petits que 1024 ) la fin
        out.write(buf,0,n);
        if (closeOnExit) {
            in.close();
            out.close();
        }
    }
0
KX Messages postés 16761 Date d'inscription   Statut Modérateur Dernière intervention   3 020
 
Bonjour,

Tu pars du principe que si la lecture ne renvoit pas 1024 alors c'est la fin. Or il peut y avoir moins de 1024 octets une fois, voire même 0, et pourtant la lecture n'est pas terminée. Cela peut venir d'une latence sur le réseau (ce qui se passerait par exemple si tu téléchargeais un fichier sur internet) ou alors d'une attente à l'autre bout du canal de communication.
Le seul moyen de garantir que la communication est vraiment terminée c'est le -1 (c'est écrit dans la documentation de la méthode read), si tu n'as jamais -1 c'est parce que le flux est resté ouvert du côté de l'écriture. Typiquement si tu lis directement sur System.in, le flux du clavier, celui-ci ne se ferme jamais tout seul, et tu pourrais le lire indéfiniment sans avoir de -1, et lorsque plus rien n'est écrit, tu as 0 octets lus pendant longtemps, mais dès que retapes à nouveau sur le clavier, tu recommences à lire des données...

PS. J'ai modifié ton message pour rajouter les balises de codes : <code java></code>
-1
Bob573
 
Re-Bonjour.

C'est vrai...

Merci de ton aide...
0
azerty
 
et la class Commun on en fait quoi ?
0
KX Messages postés 16761 Date d'inscription   Statut Modérateur Dernière intervention   3 020
 
Bonjour,

C'est quoi ton problème avec la classe Commun ?
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Utilisateur anonyme
 

Bonjour...
Bien que ce sujet doive être enterré... pour ceux qui cherchaient (comme moi) à transférer un fichier d'un client au serveur, qui le retransmettait à un client, sans fermer des sockets, je me suis contenté d'un code comme ça:

Client envoyeur:

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;

public class Transfert {
    public static void transfert(InputStream in, OutputStream out) throws IOException {
        byte buf[] = new byte[1024];
        
        int n;
        while((n=in.read(buf))!=-1){
            out.write(buf,0,n);
        }
        PrintWriter outp = new PrintWriter(out);
  outp.println("!§#%%123{#done#}123%%#§!");
  outp.flush();
    }
}


Serveur:

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;

public class Transfert {
 
    public static void transfert(InputStream in, OutputStream out){
        byte buf[] = new byte[1024];
        
        int n;
        try {
         boolean cont = true;
   while(cont){
    n = in.read(buf);
       out.write(buf,0,n);
       if(isEndReached(buf)){
        cont = false;
       }
   }
   PrintWriter outp = new PrintWriter(out);
   outp.println("!§#%%123{#done#}123%%#§!");
   outp.flush();
  } catch (IOException e) {
   e.printStackTrace();
  }
    }
    
    private static String GetString(byte[] bytes){
        return new String(bytes);
    }
    
    private static boolean isEndReached(byte[] buf){
     if(GetString(buf).contains("!§#%%123{#done#}123%%#§!")){
      return true;
     }
     return false;
    }
    
}




Le client recepteur:

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class Transfert {
 
    public static void transfert(InputStream in, OutputStream out){
        byte buf[] = new byte[1024];
        
        int n;
        try {
         boolean cont = true;
   while(cont){
    n = in.read(buf);
       out.write(buf,0,n);
       if(isEndReached(buf)){
        cont = false;
       }
   }
  } catch (IOException e) {
   e.printStackTrace();
  }
    }
    
    static String GetString(byte[] bytes){
        return new String(bytes);
    }
    
    public static boolean isEndReached(byte[] buf){
     if(GetString(buf).contains("!§#%%123{#done#}123%%#§!")){
      return true;
     }
     return false;
    }
    
}



Beaucoup trouverons à redire de ce code, mais il remplit parfaitement sa fonction :)

0
pipo91 Messages postés 5 Date d'inscription   Statut Membre Dernière intervention  
 
Salut ! Omment est ce qu'on doit proceder s'il ya plusieur client et qu'on veut envoyer le fichier a un client precis ?
Merci
0
KX Messages postés 16761 Date d'inscription   Statut Modérateur Dernière intervention   3 020 > pipo91 Messages postés 5 Date d'inscription   Statut Membre Dernière intervention  
 
Bonjour,

Soit le "client" récepteur utilise le code du serveur pour obtenir le fichier.
Soit le serveur stocke le fichier envoyé avant de le transférer.
0
pater
 
est il possible d'accelerer et de reduire le transfert des donnees via UDP Socket avec Java. Si ou comment? pardon exemple concret.
Merci
0
KX Messages postés 16761 Date d'inscription   Statut Modérateur Dernière intervention   3 020
 
Bonjour,

Un bon début pour réduire le (temps ? volume ?) des données, c'est de considérer des ZipInputStream et ZipOutputStream qui vont compresser les données, ce qui a évidemment un coût en terme de calcul à l'envoi et à la réception des données, mais permet de gagner sur le transfert des données en soit.

Sinon pour UDP vs TCP regarde cet article : TCP / UDP : Quelles différences ?
0