Torna indietro   Hardware Upgrade Forum > Software > Programmazione

Marvel's Wolverine, la recensione: Logan torna protagonista in un'avventura brutale e intensa
Marvel's Wolverine, la recensione: Logan torna protagonista in un'avventura brutale e intensa
Marvel's Wolverine porta Logan in un'avventura inedita, violenta e fortemente narrativa, costruita attorno alla sua natura di combattente e al difficile rapporto con il proprio passato. Insomniac Games punta su combattimenti spettacolari, progressione e personalizzazione, inserendo l'azione in un mondo segnato dalla persecuzione dei mutanti. Un viaggio intenso, che alterna mattanza, esplorazione e momenti sorprendentemente emotivi.
DJI Romo 2: tante novità lo rendono un robot completo
DJI Romo 2: tante novità lo rendono un robot completo
Romo 2 è la seconda generazione di robot lavapavimenti di DJI, un modello che si caratterizza per la precisione nel sistema di navigazione e per il funzionamento particolarmente silenzioso. Con le modifiche introdotte in questa seconda versione, e un posizionamento di prezzo più allineato alla concorrenza, rappresenta una valida alternativa sul mercato delle soluzioni di pulizia domestica
Sony Bravia 9 II: il True RGB alla prova, dove l'LCD sfida l'OLED
Sony Bravia 9 II: il True RGB alla prova, dove l'LCD sfida l'OLED
Il primo Sony con retroilluminazione True RGB alla prova del banco di misura e dei contenuti: luminanza enorme, colori accurati in HDR e un antiriflesso molto efficace. I limiti sono due sole HDMI 2.1 e il blooming fuori asse
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 15-06-2009, 18:25   #1
alby89
Senior Member
 
Iscritto dal: Apr 2006
Messaggi: 438
[JAVA]Trasferire file binari attraverso socket

Ciao a tutti, devo fare un piccolo programma per trasferire dei file tra 2 computer.
questo è il codice del client:
Codice:
Socket socketDelClient=new Socket(ip,6789);

FileInputStream in = new FileInputStream("img.jpg");

BufferedInputStream inB=new BufferedInputStream(in);

DataOutputStream outputAlServer=new DataOutputStream(socketDelClient.getOutputStream());

byte[] vett=new byte[20];

while((inB.read(vett,0,20))!= -1)
{
outputAlServer.write(vett,0,20);
}

inB.close();
socketDelClient.close();
il programma copia i file, solo che le dimensioni non combaciano, e nel caso di una canzone ogni tanto si sentono dei disturbi...
devo modificare la dimensione del buffere?se si a quanto?
__________________
Cpu:Intel Core i7 2600k, MB:Asrock P67 Professional, Ram: Corsair Vengeance 1866Mhz 2x4Gb, VGA:Ati Radeon x1950xtx 512Mb
PS3: Fifa12, Colin Dirt 2, Gran Turismo 5, Assasins Creed: Brotherhood
alby89 è offline   Rispondi citando il messaggio o parte di esso
Old 15-06-2009, 19:19   #2
PGI-Bis
Senior Member
 
L'Avatar di PGI-Bis
 
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
read non legge necessariamente 20 byte. In più se le dimensioni del file non sono un multiplo di 20 il file di destinazione si trova necessariamente con della monnezza in coda.

Se usi un BufferedStream puoi tranquillamente leggere un byte alla volta, ci pensa lui a creare e gestire un array di byte. E' più corta che dover star lì a quantificare il numero di byte letti, inserire gli indici affinchè venga scritta solo la porzione dell'array di byte effettivamente riempita eccetera eccetera.

Codice:
FileInputStream fin = new FileInputStream(il file);
BufferedInputStream in = new BufferedInputStream(fin);
BufferedOutputStream out = new BufferedOutputStream(client.getOutputStream());
for(int b = in.read() ; b != -1; b = in.read()) out.write(b);
Sarebbe forse meglio mandare il numero di byte che saranno trasmessi prima del file vero e proprio, in modo da dare un'idea all'altro capo della connessione di quanta roba stia arrivando.

Il tutto viene molto meglio coi canali che con i flussi. A occhio:

Codice:
FileChannel in = new FileInputStream(il file).getChannel();
WritableByteChannel out = Channels.newChannel(socket.getOutputStream());
ByteBuffer size = ByteBuffer.allocate(8);
size.putLong(in.size()).flip();
ByteBuffer data = ByteBuffer.allocate((int)in.size());
while(data.hasRemaining()) in.read(data);
data.flip();
while(size.hasRemaining()) out.write(size);
while(data.hasRemaining()) out.write(data);
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me!
PGI-Bis è offline   Rispondi citando il messaggio o parte di esso
Old 15-06-2009, 19:50   #3
alby89
Senior Member
 
Iscritto dal: Apr 2006
Messaggi: 438
grazie per la risposta.
avevo pensato anch'io alla monnezza in coda, solo che se leggo un byte alla volta il trasferimento diventa molto lento.
Non esiste un "algoritmo" per poter velocizzare il trasferimento e allo stesso tempo non creare monnezza alla fine del file?
__________________
Cpu:Intel Core i7 2600k, MB:Asrock P67 Professional, Ram: Corsair Vengeance 1866Mhz 2x4Gb, VGA:Ati Radeon x1950xtx 512Mb
PS3: Fifa12, Colin Dirt 2, Gran Turismo 5, Assasins Creed: Brotherhood
alby89 è offline   Rispondi citando il messaggio o parte di esso
Old 15-06-2009, 19:56   #4
PGI-Bis
Senior Member
 
L'Avatar di PGI-Bis
 
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
Se il flusso è di tipo Buffered il trasferimento per byte non causa rallentamenti dovuti al fatto che mandi-leggi un byte alla volta perchè dietro le quinte lui li accumula e ne manda-legge a blocchi.

Assicurati che siano dotati di buffer sia il flusso in lettura dal file che il flusso in scrittura sul socket.
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me!
PGI-Bis è offline   Rispondi citando il messaggio o parte di esso
Old 15-06-2009, 20:21   #5
alby89
Senior Member
 
Iscritto dal: Apr 2006
Messaggi: 438
Quote:
Originariamente inviato da PGI-Bis Guarda i messaggi
Se il flusso è di tipo Buffered il trasferimento per byte non causa rallentamenti dovuti al fatto che mandi-leggi un byte alla volta perchè dietro le quinte lui li accumula e ne manda-legge a blocchi.

Assicurati che siano dotati di buffer sia il flusso in lettura dal file che il flusso in scrittura sul socket.
eppure sono buffer e se metto cm n byte 1 ci mette 30 sec circa per 3 mb, mentre se metto n=20 ci mette 1-2 sec..
__________________
Cpu:Intel Core i7 2600k, MB:Asrock P67 Professional, Ram: Corsair Vengeance 1866Mhz 2x4Gb, VGA:Ati Radeon x1950xtx 512Mb
PS3: Fifa12, Colin Dirt 2, Gran Turismo 5, Assasins Creed: Brotherhood
alby89 è offline   Rispondi citando il messaggio o parte di esso
Old 15-06-2009, 20:49   #6
PGI-Bis
Senior Member
 
L'Avatar di PGI-Bis
 
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
E' strano perchè è come dire che il BufferedXYZStream in verità non ha un buffer. Non è che scrivi anche un byte alla volta sul file in ricezione?

Comunque sono questioni scolastiche: coi canali il "raw input" si fa molto meglio e la bufferizzazione - termine orrendo - è precotta. Usa i canali.

FileChannel in = new FileInputStream(il file).getChannel();

per aprire un canale sul file. Per leggere i dati da un canale usi un Buffer, nella fattispecie un ByteBuffer. I Buffer hanno la meravigliosa proprietà di sapere da soli quanti byte sono stati inseriti, fin dove devano essere letti e cose così. In pratica dato il canale "in" se il file non ha dimensioni enormi puoi creare un Buffer che contenga tutto quanto il file:

ByteBuffer buffer = ByteBuffer.allocate((int)in.size());

Poi riempi il buffer dal canale:

while(buffer.hasRemaining()) in.read(buffer);

la "read" legge quanti più byte possibile e siccome il buffer ha le stesse dimensioni del file sottostante sappiamo che il file è stato completamente letto quando il buffer non ha più spazio rimanente.

Una volta riempito buffer lo "riavvolgi" (cioè lo prepari ad un nuovo uso):

buffer.flip() oppure buffer.rewind()

A questo punto puoi scaricarlo in un canale in uscita. Per un socket "normale" ottieni un canale in uscita con:

WritableByteChannel out = Channels.newChannel(socket.getOutputStream());

Per rendere più breve l'operazione di lettura dall'altra parte del socket puoi inviare prima dei dati del file la lunghezza del file stesso, cioè il numero di byte che compongono il file. Pigli la dimension del file:

long size = in.size();

La incapsuli in un ByteBuffer:

ByteBuffer sizeBuffer = ByteBuffer.allocate(8);
sizeBuffer.putLong(size).flip();

e spari il buffer nel canale in uscita del socket:

while(sizeBuffer.hasRemaining()) out.write(sizeBuffer);

La scrittura del file è come la lettura: finchè il buffer ha dei byte non ancora esaminati dal canale, lo passi al canale:

while(buffer.hasRemaining()) out.write(buffer);

Anche qui il ciclo tenta di inviare il numero più alto possibile di byte in un blocco solo. Se non ci riesce ritenta al passaggio successivo finchè tutti i byte non sono stati inviati.

Lato client fai una cosa simile. Prendi il socket e crei un canale in entrata:

ReadableByteChannel in = Channels.newChannel(socket.getInputStream());

Sai di aver mandato prima di tutto la dimensione del file in un long, che sono 8 byte. Quindi leggi 8 byte:

ByteBuffer sizeBuffer = ByteBuffer.allocate(8);
while(sizeBuffer.hasRemaining()) in.read(sizeBuffer);

dopo riavvolgi il buffer:

sizeBuffer.rewind();

e ottieni la dimensione con getLong():

long size = sizeBuffer.getLong();

A questo punto sai quanti byte devi leggere. Puoi creare un buffer per contenerli tutti:

ByteBuffer data = ByteBuffer.allocate((int)size);

e riempirlo dal socket:

while(data.hasRemaining()) in.read(data);

Anche qui legge il numero massimo possibile di byte in una volta sola, gestisce da solo indici e cursori e compagnia bella.

Una volta riempito il buffer con i dati del file puoi riavvolgerlo:

data.rewind();

e spararlo in un file:

FileChannel out = new FileOutputStream(un file).getChannel();
while(data.hasRemaining()) out.write(data);

e hai fatto, con il tuo bel buffering, al top della banda disponibile, senza dover star lì a contare.
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me!
PGI-Bis è offline   Rispondi citando il messaggio o parte di esso
Old 15-06-2009, 21:42   #7
alby89
Senior Member
 
Iscritto dal: Apr 2006
Messaggi: 438
grazie mille per la spiegazione
__________________
Cpu:Intel Core i7 2600k, MB:Asrock P67 Professional, Ram: Corsair Vengeance 1866Mhz 2x4Gb, VGA:Ati Radeon x1950xtx 512Mb
PS3: Fifa12, Colin Dirt 2, Gran Turismo 5, Assasins Creed: Brotherhood
alby89 è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


Marvel's Wolverine, la recensione: Logan torna protagonista in un'avventura brutale e intensa Marvel's Wolverine, la recensione: Logan torna p...
DJI Romo 2: tante novità lo rendono un robot completo DJI Romo 2: tante novità lo rendono un ro...
Sony Bravia 9 II: il True RGB alla prova, dove l'LCD sfida l'OLED Sony Bravia 9 II: il True RGB alla prova, dove l...
Geely EX5, un mese al volante: il SUV elettrico cinese che ci ha sorpreso (quasi) senza riserve Geely EX5, un mese al volante: il SUV elettrico ...
Mova Z70 Ultra Roller Complete: motore potente, rullo di lavaggio e l'IA a guidare Mova Z70 Ultra Roller Complete: motore potente, ...
Avio si prepara ai test del Dimostratore...
Space Pioneer ha annunciato le cause del...
Anthropic avrebbe nuovi antibiotici cont...
Scoperto un 'moltiplicatore nascosto' ne...
DREO: a IFA 2026 4 novità fra cui...
Slackbot genera dashboard e microsite de...
Idrogeno, nuova cella a combustibile rag...
Con la NASA fuori dai giochi, l'ESA risc...
Una falla di ChatGPT permette di estrapo...
Piano clima, 1,34 miliardi per il bonus ...
Porsche esce definitvamente da Bugatti R...
NVIDIA App aggiunge una delle funzioni p...
Come sarebbe il mondo se la luce viaggia...
Titanio, ceramica e zaffiro per HUAWEI W...
Taglio delle accise sul gasolio prorogat...
Chromium
GPU-Z
OCCT
LibreOffice Portable
Opera One Portable
Opera One 106
CCleaner Portable
CCleaner Standard
Cpu-Z
Driver NVIDIA GeForce 546.65 WHQL
SmartFTP
Trillian
Google Chrome Portable
Google Chrome 120
VirtualBox
Tutti gli articoli Tutte le news Tutti i download

Strumenti

Regole
Non Puoi aprire nuove discussioni
Non Puoi rispondere ai messaggi
Non Puoi allegare file
Non Puoi modificare i tuoi messaggi

Il codice vB è On
Le Faccine sono On
Il codice [IMG] è On
Il codice HTML è Off
Vai al Forum


Tutti gli orari sono GMT +1. Ora sono le: 21:59.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Served by www3v