[Risolto][Java] Trasferimento di file via socket

Linguaggi di programmazione: php, perl, python, C, bash e tutti gli altri.
raider91
Prode Principiante
Messaggi: 164
Iscrizione: giovedì 28 marzo 2013, 13:09
Desktop: gnome-fallback
Distribuzione: ubuntu 12.04.2 LTS x86_64

[Risolto][Java] Trasferimento di file via socket

Messaggio da raider91 »

Ciao ragazzi come da titolo sto cercando di implementare un modo affinchè si possano trasferire file da un pc ad un altro tramite socket.Ho avuto però dei problemi.In pratica il server intercetta il file inviato dal client però non salva niente,cioè non salva il file intercettato.Questo perchè ho notato che il client tecnicamente non invia niente in quanto il file intercettato dal server ha grandezza 0.Non riesco a capire dove sbaglio.Riuscite ad aiutarmi?Di seguito posto il codice sia del server che del client:

Lato server:

Classe Main:

Codice: Seleziona tutto

public class Main {

    public static void main(String[] args) throws IOException {
      
        int n_port=2000;
        ServerSocket server=new ServerSocket(n_port); //Creiamo la serversocket sulla porta 2000;
        System.out.println("Server "+server.getInetAddress().getHostAddress()+" in listening!");
        
        //Ciclo infinito per permettere l'ascolto e la ricezione di più client;
        while(true){
        Socket client=server.accept(); //Immagine del client sul server;
        Server thread=new Server(client);
        Thread worker=new Thread(thread);
        worker.start();
        }
        
        
    }
    
}

Classe Server(permette di gestire i trasferimenti):

Codice: Seleziona tutto

public class Server extends Thread{
    
    private Socket c;
    private String ip_client;
    private String mess_letto;
    private int count;
    private String matr_t;
    
    public Server(Socket client) throws IOException{
        this.matr_t=null;
        this.count=0;
        this.c=client;
        this.ip_client=this.c.getInetAddress().getHostName();
        System.out.println("Connessione in ingresso con il client "+this.ip_client);
    }

@Override
public void run(){
  
                          //Dichiariamo i buffer;
                          BufferedReader reader=null;
                          Writer writer=null;
        
                                                     //Instanziamo i buffer;
            reader=new BufferedReader(new InputStreamReader(this.c.getInputStream()));
            writer=new OutputStreamWriter(this.c.getOutputStream());

                    String mess="\nInserisci il path del file da caricare: ";
                    writer.write(mess);
                    writer.flush();
                    
                    try{
                    //Intercetto il file;
                    ObjectInputStream inps=new ObjectInputStream(this.c.getInputStream());
                    File infile=(File) inps.readObject();
                    File savefile=new File("/home/utente/Scrivania/cartella/"+this.matr_t+"/"+infile.getName());
                    this.save(infile,savefile);
                    }catch(ArrayIndexOutOfBoundsException e){
                          continue;
                    }
                        catch(Exception ex){
                          //Ignoro;
                    }
                      
}

    //Metodo per permettere di salvare i file ricevuti;
    public void save(File in,File out) throws FileNotFoundException, IOException{
         System.out.println("Intercettiamo il file"+in.getName());
         System.out.println("Dimensione del file"+in.length());
         
         FileInputStream fis=new FileInputStream(in);
         FileOutputStream fos=new FileOutputStream(out);
         byte []buff=new byte[1024];
         int i=0;
         while((i=fis.read(buff))!=-1){
            fos.write(buff,0,i);
         }
         fis.close();
         fos.close();
         
         System.out.println("Ricezione completata");
    }

}



Lato client:

Codice: Seleziona tutto

public class Main {


public static void main(String [] args) throws IOException, InterruptedException{
     
       int k=0; 
       Socket s=null;
       PrintWriter out=null;
       BufferedReader in=null;
       Scanner buff_in=new Scanner(System.in);

       System.out.println("Stiamo provando a collegarci al server [0.0.0.0]");

       try{
              s=new Socket("192.168.0.110",2000);
              out=new PrintWriter(s.getOutputStream(),true); //Instanziamo il buffer di output;
              in=new BufferedReader(new InputStreamReader(s.getInputStream()));

       }catch(UnknownHostException e){
                //Ignoro;
            }
         catch(IOException e){
               //Ignoro;
             }

                      String path=buff_in.next(); //Inseriamo il path;
                      Invia ogg=new Invia();
                      ogg.sendFile(new File(path),s); //Inviamo il file al server;
}
Classe Invia:

Codice: Seleziona tutto


public class Invia {
    
    
        public void sendFile(File file,Socket s) throws IOException{
               
               ObjectOutputStream oos=new ObjectOutputStream(s.getOutputStream());
               oos.reset();
               oos.writeObject(file);
               oos.flush();
               oos.close();
        
        }
    
}
Ultima modifica di raider91 il giovedì 25 giugno 2015, 12:53, modificato 1 volta in totale.
Avatar utente
nuzzopippo
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1638
Iscrizione: giovedì 12 ottobre 2006, 11:34

Re: [Java] Trasferimento di file via socket

Messaggio da nuzzopippo »

Ciao, ho provato qualcosa di analogo giusto qualche giorno fa, avendo i Tuoi stessi problemi, risolti un po' con l'aiuto di google, un po' giochicchiandoci.

Il mio è stato un semplice test propedeutico ad un programma di chat ed invio files da tenersi in una lan locale e mi son limitato ad eseguire i test in "localhost" (IP = 127.0.0.1) poi messo da parte per vedere la gestione di configurazione degli Ip da utilizzare da scegliere nelle varie sotto-reti della lan.

A quanto ho riscontrato i problemi sorgono nelle istruzioni di invio del file quando si utilizzano i metodi di scrittura degli oggetti (nella Tua classe "Invia" l'istruzione oos.writeObject(file);) che analogamente alle Tue indicazioni risulta vuota come ricezione, circostanza non mi è riuscito di risolvere.
Personalmente ho superato il punto utilizzando stream di byte, ma riservandomi di approfondire, ed inviando i dati sul file da trasmettere quali parametri.

Ferma restando la necessità di approfondire Ti indico, nel caso possa esserTi utile, un semplice test funzionale che ho fatto per verificare i metodi possibili, e funziona.

Lato server :

Codice: Seleziona tutto

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;

public class Send {
	ServerSocket ss;
	Socket s;
	
	public Send() throws IOException {
		int port = 9999;
		String path_file = "/home/xxxxxx/tests/server/Dolci_di_Sardegna.pdf";
		long dim_file = 1075091;
		String nome = "Dolci_di_Sardegna.pdf";
		// mi connetto al client
		s = connect(port);
		// invio il file
		send_file(path_file, nome, dim_file);
	}
	
	// funzione per connettermi al client
	public Socket connect(int port) {
		Socket sock = null;
		try {
			ss = new ServerSocket(9999);
			System.out.println("* Attendo un client");
			sock = ss.accept();
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		System.out.println("* Connesso con successo");
		return sock;
	}
	
	public void invia_parametri(String nome, long dimensione, ObjectOutputStream oos) {
		String param = nome + "," + dimensione;
		try {
			oos.flush();
			oos.writeObject(param);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public void send_file(String path_file, String nome, long dim_file) throws IOException {
		System.out.println("* Inizio processo di invio file");
		String path = path_file;
		long dim = dim_file;
		FileInputStream fis = null;
		ObjectOutputStream oos;
		try {
			fis = new FileInputStream(path);
			oos = new ObjectOutputStream(s.getOutputStream());
			byte[] buff = new byte[1024];
			int read;
			long tot = 0;
			// invio i dati del file al client
			invia_parametri(nome, dim, oos);
			// inizio fase di lettura
			System.out.println("* Inviati : ");
			oos.flush();
			while((read = fis.read(buff)) != -1) {
				tot += read;
				System.out.println(" - " + tot + " byte");
				oos.write(buff, 0, read);
				oos.flush();
			}
			System.out.println("** File inviato con successo");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}
	
	public static void main(String args[]) throws IOException {
		new Send();
	}
}
Come puoi leggere, la classe Send è un server che si mette in ascolto in attesa di un client, ad avvenuta connessione immediatamente trasmette i parametri del file (nome e dimensione) tramite un ObjectOutputStream, ripulisce il flusso ed invia un flusso di byte presi da un FileInputStream, il cuore dell'invio è il metodo "send_file"

dal lato client :

Codice: Seleziona tutto

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class Get {
	Socket s;
	
	public Get() throws IOException {
		String ip = "127.0.0.1";
		int port = 9999;
		String default_dir = "/home/xxxxxx/tests/client/";
		// mi connetto al server
		boolean connected = connect(ip, port);
		if (connected == false) {
			System.out.println("Non esiste alcun server sulla porta " + port);
			System.exit(0);
		}
		// avvio la ricezione del file
		get_File(default_dir);
	}
	
	// funzione per connettersi al server
	public boolean connect(String ip, int port) {
		boolean result = false;
		try {
			s = new Socket(ip, port);
			result = true;
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return result;
	}
	
	public String[] ottengo_parametri(ObjectInputStream ois) {
		String parametri_file[] = null;
		try {
			String param = (String) ois.readObject();
			parametri_file = param.split(",");
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		return parametri_file;
	}
	
	public void get_File(String dest) throws IOException {
		System.out.println("* Inizio il processo di ricezione");
		String destinazione = dest;
		int read;
		long tot = 0;
		ObjectInputStream ois = new ObjectInputStream(s.getInputStream());
		String [] param_file = ottengo_parametri(ois);
		String nome = param_file[0];
		long dimensione = Long.parseLong(param_file[1]);
		// Sream per il salvataggio del file su disco
		File file = new File(destinazione + nome);
		// apro outputStram
		FileOutputStream fos = new FileOutputStream(file, true);
		byte[] buf = new byte[1024];
		System.out.println("* Ricevo : ");
		// prendo i dati a pacchetti di 1024 byte
		try {
			while((read = ois.read(buf)) != -1) {
				tot += read;
				System.out.println(" - " + tot + " byte");
				// scrivo il pacchetto sul disco
				fos.write(buf, 0, read);
			}
		} catch (java.net.SocketException e) {
			e.printStackTrace();
		}
		if (tot == dimensione) {
			System.out.println("* File ricevuto con successo");
		} else {
			System.out.println("$$ ERRORE - c'è stato qualche problema!");
		}
	}
	
	public static void main (String args[]) throws IOException {
		new Get();
	}
}
La classe client (Get) è simmetrica alla server, appena stabilita la connessione viene avviato il processo di ricezione del file, in primo luogo vene aperto un ObjectInputStream (ois) per recepire e processare i dati del file che si sta ricevendo, viene fatto con il metodo "ottengo_parametri", processati i parametri viene aperto un FileOutputStream (fos) che provvede scrivere un buffer di byte letto sempre dallo ObjectInputStream "ois"
Il cuore del client è il metodo "get_File"

Il file scambiato è un pdf a caso risiedente nella direttrice del server e salvato in quella del client, i dati (parametri) del file sono inseriti a mano, non mi sono complicato quello che è un semplice test.

Spero Ti sia utile e rimango in attesa con Te di eventuali migliori indicazioni
Fatti non foste a viver come bruti ...
raider91
Prode Principiante
Messaggi: 164
Iscrizione: giovedì 28 marzo 2013, 13:09
Desktop: gnome-fallback
Distribuzione: ubuntu 12.04.2 LTS x86_64

Re: [Java] Trasferimento di file via socket

Messaggio da raider91 »

Ciao ti ringrazio del tuo aiuto.Comunque sono riuscito a risolvere e a capire dov'era il problema.In pratica come ho implementato io la classe Invia è sbagliatissimo.Il concetto è che non si deve trasferire un java.io.File (che rappresenta solo una "astrazione" di un percorso sul file-system,quindi un path) ma proprio un file da una macchina ad un'altra.Quindi se client e server sono due macchine distinte devo poter inviare dalla macchina mittente a quella destinataria il file bit per bit e non semplicemente il path del file che giustamente il ricevente non può aprire.L'unico modo per inviare un file dunque è aprire in letture dalla macchina mittente il file da inviare e leggere il file e inserire il contenuto in un buffer.Tale buffer dovrà essere poi inviato man mano alla macchina di destinazione che dovrà semplicemente leggerlo sul canale di input.Spero di essere stato chiaro e di non aver fatto confusione.Alla prossima!
Scrivi risposta

Ritorna a “Programmazione”

Chi c’è in linea

Visualizzano questa sezione: 0 utenti iscritti e 4 ospiti