Visualizzazione dei risultati da 1 a 5 su 5
  1. #1
    Utente di HTML.it L'avatar di AtoXx
    Registrato dal
    Nov 2007
    Messaggi
    119

    Socket UDP trasferimento file da server a client

    Ciao a tutti, ho realizzato un client ed un server UDP in cui il client chiede al server di mandargli un determinato file. Invio datagrammi con parte dati di dimensione 1024byte. Tutto funziona con file piccoli, diciamo inferiori a 8KB, ma appena mando file di grandi dimensioni è come se il client non ricevesse tutti i pacchetti inviati dal server. Ho pensato che il problema possa essere che il server manda troppi pacchetti saturando il buffer di ricezione del client e conseguente perdita di pacchetti. Per questo ho messo tra l'invio di un pacchetto, da parte del server, e l'altro un delay di circa 35ms e così funziona ma a discapito del throughput. A qualcuno è mai capitata una cosa del genere?Mi sembra davvero strano come problema.

    Ho allegato i file sorgenti

    Codice Server
    codice:
        import java.io.*;
    import java.net.*;
    
    
    public class FServerUDP {
    
            public static final int PORT = 4446; 
            //public static final String FILE = "file.txt";
            DatagramSocket socket;
            
            public FServerUDP(){
                try {
                    // creazione della socket datagram
                    socket = new DatagramSocket(PORT);
                    //System.out.println("FServerUDP: avviato");
                } catch (SocketException e) {System.err.println("Unable to create the socket");}
                
            }
            
            public static long dimFile(File f){
                f.length();
                //System.out.println("Dimensione "+ f.getName()+": " +f.length()+" bytes");
                return f.length();
            }
    
            public static void main(String[] args) throws IOException {
                
                FServerUDP server=new FServerUDP();
                
                 //Informazioni sul Server in ascolto
                 InetAddress indirizzo = server.socket.getLocalAddress();
                 String stringaServer = indirizzo.getHostAddress();
                 int portServer = server.socket.getLocalPort();
                 System.out.println("Server UDP: "+ stringaServer + " porta: " + portServer);
                
                
                 while(true){
                         System.out.print("In ascolto...");
                        byte[] buf = new byte[1024]; //in questo buffer ho il nome del file da inviare al client
                    
                        // ricezione della richiesta 
                        DatagramPacket packet = new DatagramPacket(buf, buf.length);
                        server.socket.receive(packet);
                        String rcv= new String(packet.getData());
                        System.out.println("Ho ricevuto: "+rcv.trim());
                        File file= new File(rcv.trim());
                        long dimensioneFile=dimFile(file);
                                        
                        FileInputStream fis=new FileInputStream (file);
                                            
                        //System.out.println("Dimensione file: "+ fis);
                        if (dimensioneFile < Integer.MIN_VALUE || dimensioneFile > Integer.MAX_VALUE) {
                            System.err.println(dimensioneFile + " cannot be cast to int without changing its value.");
                            System.exit(1);
                        }
                        
                        int i=(int)dimensioneFile;//i è la dimensione del file totale
                        
                        int k=i/1024;//k mi dice quanti pacchetti devo inviare da 1024byte
                        
                        
                        if(k==0 || i%1024>0){
                            k++;
                            System.out.println("pacchetti: "+k);
                            }
                        
                        byte[] bufFile=new byte[i];//metto il file in memoria
                        
                                
                        
                        //metto tutto il file in un buffer di dim uguale a quella del file
                        for(int ii=0;ii<i;ii++){
                            bufFile[ii]=(byte)fis.read();
                                        }
                        fis.close();
                    
                        
                        /*********************************/
                        /*Invio il primo pacchetto con la dimensione del file!!*/
                        InetAddress address = packet.getAddress();
                        int port = packet.getPort();
                        System.out.println("Ip: "+address+" Porta: "+port);
                        String Filedim=String.valueOf(i);
                        byte[] bufDim=new byte[4];
                        bufDim=Filedim.getBytes();
                        
                        packet = new DatagramPacket(bufDim, bufDim.length, address, port);
                        server.socket.send(packet);
                        /*********************************/
                        
                        for(int idx=0;idx<k;idx++){//invio tanti pacchetti da 1024bytes per quant'è la dimensione del file
                            if(idx==k-1)
                                System.out.println("Ultimo pacchetto n#"+idx);
                            int byteDaInviare=1024;
                            
                            if(idx==k-1)//se è l'ultimo pacchetto da inviare, calcolo quanti byte mi restano da mandare
                                {
                                    byteDaInviare= i - (idx*1024);
                                    System.out.println("L'ultimo pacchetto contiene: "+byteDaInviare+ "  idx:"+idx);
                                }
                            //System.out.println("offset: "+idx*1024+"  length" +byteDaInviare);                        
                            packet = new DatagramPacket(bufFile, idx*1024, byteDaInviare, address, port);
                            server.socket.send(packet);
                            /*try {
                                Thread.sleep(35);
                            } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }*/
                        }//chiude il for
                        
                    
            
                System.out.print("Finito mi rimeetto in ascolto...");
            }
                //System.out.println("Chiudo la socket...");
                //server.socket.close();
            }
    
        }
    Se vedete nel codice del Server c'è una parte commentata in cui faccio una sleep Thread.sleep(35), mettendo quella il trasferimento del file va a buon fine.




    Codice Client
    codice:
    import java.io.*;
    import java.net.*;
    
    public class FClientUDP {
            
            public static void main(String[] args) throws IOException {
                //     creazione della socket datagram
    
                DatagramSocket socket = new DatagramSocket(5555);
                System.out.println("Client: avviato");
                
                //     creazione e invio del pacchetto di richiesta
                byte[] buf = new byte[512];
                BufferedReader stdIn= new BufferedReader(new InputStreamReader(System.in));
                InetAddress addr;
                if (args.length == 0) 
                    addr = InetAddress.getByName(null);
                else 
                    addr = InetAddress.getByName(args[0]);
                            
                DatagramPacket packet = new DatagramPacket(buf, buf.length, addr, 4446);
                
                while(true){
                    //invio richiesta
                    
                     System.out.print("Inserisci il dato da scaricare: ");
                     String userInput = stdIn.readLine();
                
                     buf = userInput.getBytes();
                    
                     packet.setData(buf);
                     packet.setLength(userInput.length());
             
                     //Invio del pacchetto sul Socket
                     socket.send(packet);
                                    
                    
                    
                    
                    //System.out.println("Attendo il trasferimento del file...");
                    boolean flag=true;
                    int dimFile=0;
                    int numPack=0;
                    int dimFile2=0;
                    
                    long start=0;
                    do{
                        
                        byte[] bufr=new byte[1024];
                        DatagramPacket packetr = new DatagramPacket(bufr, bufr.length);
                                    
                        socket.receive(packetr);
                        if(flag)
                            { 
                                flag=false;
                                String asd=new String(packetr.getData());
                                start=System.currentTimeMillis();
                                dimFile=Integer.parseInt(asd.trim());
                                dimFile2=dimFile;
                                
                                continue;
                            }
                        int dimPack=packetr.getLength();
                        
                        byte[] rx=packetr.getData();
                    
                        byte[] rx2=new byte[dimPack];
                        boolean flag2=false;
                        if(dimPack!=1024){
                            flag2=true;
                            for(int a=0;a<dimPack;a++){
                                rx2[a]=rx[a];
                            }
                        }
                        
                    FileOutputStream fos = new FileOutputStream(userInput,true);
                    if(flag2){
                    
                        fos.write(rx2);
                    }
                    
                    else fos.write(rx);                                
                    dimFile-=dimPack;
                    dimFilemomentaneo+=dimPack;    
                    
                    
                    
            
                    numPack++;
                    if(dimFile==0){                    
                        fos.flush();
                    
                        long tmp=System.currentTimeMillis()- start;
                        
                        float throughput=( ( (float)dimFile2 / (float)(1024*1024) ) / ((float)tmp/(float)1000) )*8;//Mb/s
                        System.out.println("Throughput: "+throughput+" Mb/sec");
                        fos.close();
                        System.out.println("\nChiudo il file");}
                    
                    } while(dimFile>0);
                    
                        break;
                    
                }
                
                System.out.println("Chiudo il client...");
                socket.close();
            }
        
    }
    File allegati File allegati
    Ultima modifica di AtoXx; 12-04-2014 a 13:21

  2. #2
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da AtoXx Visualizza il messaggio
    Ciao a tutti, ho realizzato un client ed un server UDP in cui il client chiede al server di mandargli un determinato file. Invio datagrammi con parte dati di dimensione 1024byte. Tutto funziona con file piccoli, diciamo inferiori a 8KB, ma appena mando file di grandi dimensioni è come se il client non ricevesse tutti i pacchetti inviati dal server. Ho pensato che il problema possa essere che il server manda troppi pacchetti saturando il buffer di ricezione del client e conseguente perdita di pacchetti. Per questo ho messo tra l'invio di un pacchetto, da parte del server, e l'altro un delay di circa 35ms e così funziona ma a discapito del throughput. A qualcuno è mai capitata una cosa del genere?Mi sembra davvero strano come problema.
    Appena ho un po' più di tempo potrei anche esaminare in dettaglio il tuo codice. A prima vista però ho la (netta) sensazione che fai parecchie cose e "giri" inutili (più alcune dubbie).

    Anche ammesso di far "quadrare" e funzionare il tuo codice, un trasferimento di file in quel modo su UDP rimane poco più che un "giocattolo", giusto un esercizio per usare DatagramSocket. Infatti UDP è un protocollo "connectionless" ed ha di per sé una serie di fattori negativi:
    - non c'è garanzia che un pacchetto arrivi a destinazione (e UDP non fornisce alcun acknowledge al mittente, di per sé).
    - i pacchetti possono arrivare in un ordine diverso da quello con cui sono stati inviati.
    - a seconda della tipologia/infrastruttura di rete più o meno complessa, i pacchetti possono anche arrivare duplicati N volte.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  3. #3
    Utente di HTML.it L'avatar di AtoXx
    Registrato dal
    Nov 2007
    Messaggi
    119
    conosco i pregi e difetti dell'udp, ma nel mio caso dovrà essere usato per la comunicazione diretta tra 2 pc, collegandoli direttamente con un cavo ethernet.
    Sicuramente avrei potuto scriverlo meglio .

    Ma quel problema che ho pensato si può presentare?Cioè che si riempie il buffer in ricezione associato al socket(parlo del client ovviamente)..


    Ti dico brevemente come funziona la comunicazione che ho fatto:
    praticamente il client prende da tastiera il nome del file che vuole gli sia spedito e lo mando al server. Qui il server prende il file, lo legge e lo mette in un buffer di byte. A questo punto invio tanti pacchetti di dati da 1024byte. Il primo di questi pacchetti conterrà la dimensione del file cosicchè il client sà quando ha ricevuto tutti i pacchetti e quindi può salvare il file.

  4. #4
    Utente di HTML.it L'avatar di AtoXx
    Registrato dal
    Nov 2007
    Messaggi
    119
    Ho fatto un'altra prova, ho sniffato i pacchetti ed ho visto che anche nel caso in cui il client "sembra" non ricevere tutti i pacchetti, i pacchetti sono stati inviati. Quindi potrebbe essere che si riempie il buffer di ricezione del client....
    ho provato con file più piccoli di 8kB(che è la dimensione del buffer associata al mio socket, l'ho visto con socket.getReceiveBufferSize() ) ed il problema non si presenta mai. Però mi sembra alquanto strano

  5. #5
    Utente di HTML.it L'avatar di AtoXx
    Registrato dal
    Nov 2007
    Messaggi
    119
    Nessuno sa dirmi qualcosa?

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.