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();
}
}