|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Senior Member
Iscritto dal: Sep 2005
Città: Torino
Messaggi: 606
|
[JAVA] Stream e socket
Ho appena cominciato ad usare il package java.net per la connessione tra socket(client+server), ma ancora non mi sono chiare molte cose, tanto che adesso sto confondendo anche gli stream che pensavo di aver capito bene!!!
Per esempio ho questa classe: (scusate gli eventuali errori..l'ho scritta così su due piedi) Codice:
import java.net.*;
import java.io.*;
public class prova {
public static void main(String...args) throws Exception {
ServerSocket server = new ServerSocket(12345);
boolean listening = true;
while (listening) {
Socket client = server.accept();
BufferedReader r = new BufferedReader(new InputStreamReader(client.getInputStream()));
PrintWriter w = new PrintWriter(client.getOutputStream());
//...
// qui faccio le operazioni che mi servono
//...
r.close();
w.close();
client.close();
server.close();
}
}
}
__________________
"Se proprio dovete piratare un prodotto, preferiamo che sia il nostro piuttosto che quello di qualcun altro." [Jeff Raikes] "Pirating software? Choose Microsoft!" |
|
|
|
|
|
#2 | |
|
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Quote:
Veniamo alla tua domanda finale cioè come far passare un file tra client e server: semplice, devi gestirlo tu! Da un socket puoi solo ottenere un InputStream e OutputStream. Cosa scrivi e leggi devi stabilirlo tu, magari con un protocollo apposito. A parte il fatto che dovresti stabilire come scegliere il file da trasferire ma in sostanza dovresti fare così: da un lato apri il file con FileInputStream, leggi a blocchi di byte e li mandi sull'OutputStream del socket. Dall'altra parte fai esattamente l'opposto. Leggi dall'InputStream del socket e scrivi su un FileOutputStream. Ma ripeto ... è una cosa che devi fare tu.
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
|
|
|
|
|
|
#3 |
|
Senior Member
Iscritto dal: Sep 2005
Città: Torino
Messaggi: 606
|
confidavo in una tua risposta!
ora vado a casa ed applico. grazie mille!!!
__________________
"Se proprio dovete piratare un prodotto, preferiamo che sia il nostro piuttosto che quello di qualcun altro." [Jeff Raikes] "Pirating software? Choose Microsoft!" |
|
|
|
|
|
#4 | |
|
Senior Member
Iscritto dal: Sep 2005
Città: Torino
Messaggi: 606
|
Quote:
nel copiare i file dal server al client si interrompe la lettura/scrittura e attende la pressione del tasto "invio", quindi se apro il file scaricato (lato client, per intenderci, anche se dovrebbe essere lo stesso...) ogni 1024 byte (la grandezza del buffer) c'ho il carattere "quadrato!!" che dovrebbere corrispondere all'invio non correttamente codificato (sto spiegando proprio male!! posto il codice della parte interessata: Codice:
public final int PORT = 12345;
private ServerSocket server = new ServerSocket(PORT);
private Socket client;
{
// ...
boolean listening = true;
while (listening)
{
client = server.accept();
String fileOrigine = "c:\\origine.txt";
String fileDestinazione = "c:\\destinazione.txt";
download(fileOrigine, fileDestinazione);
client.close();
}
// ...
}
public void download(String origin, String destination) throws IOException
{
InputStream is = client.getInputStream();
OutputStream os = client.getOutputStream();
FileInputStream fis = new FileInputStream(origin);
FileOutputStream fos = new FileOutputStream(destination);
byte[] buffer = new byte[1024];
byte[] buffer2 = new byte[1024];
while(fis.read(buffer) != -1) {
os.write(buffer);
os.flush();
is.read(buffer2);
fos.write(buffer2);
fos.flush();
}
fos.close();
fis.close();
}
PPS: client e server stanno sullo stesso file...uso il telnet per connettermi al server ed inviare le stringhe di comando.
__________________
"Se proprio dovete piratare un prodotto, preferiamo che sia il nostro piuttosto che quello di qualcun altro." [Jeff Raikes] "Pirating software? Choose Microsoft!" Ultima modifica di Oceans11 : 12-12-2006 alle 19:08. |
|
|
|
|
|
|
#5 |
|
Senior Member
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12112
|
mmm..
non ho capito ke intendevi fare ma cmq il tuo programma si comporta correttamente secondo quanto scritto nel codice... Lui sta in attesa di dati sul socket e quando tu scrivi invio con telnet lo legge e lo inserisce nel buffer prima dei dati ke va a leggere nel file. Io nel frattempo mi sono messo a fare due classettine ProvaClient e ProvaServer: Codice:
import java.io.BufferedReader;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class ProvaServer {
public ProvaServer() {
try {
char[] buffer = new char[1024];
ServerSocket server = new ServerSocket(4123);
Socket socket = server.accept();
InputStreamReader isReader = new InputStreamReader(socket.getInputStream());
BufferedReader reader = new BufferedReader(isReader);
FileWriter fileWriter = new FileWriter("c:/myClasspath.mine");
while(reader.read(buffer) != -1) {
fileWriter.write(buffer);
fileWriter.flush();
}
fileWriter.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
ProvaServer server = new ProvaServer();
}
}
Codice:
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
public class ProvaClient {
public ProvaClient() {
try {
char[] buffer = new char[1024];
Socket socket = new Socket("127.0.0.1", 4123);
FileReader fileReader = new FileReader("c:/classpath.txt");
OutputStreamWriter osWriter = new OutputStreamWriter(socket.getOutputStream());
BufferedWriter writer = new BufferedWriter(osWriter);
while(fileReader.read(buffer) != -1) {
writer.write(buffer);
writer.flush();
}
writer.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
ProvaClient provaClient = new ProvaClient();
}
}
Il problema però è ke ovviamente leggendo buffer di 1000 caratteri e non eseguendo nessun filtro il file destinazione sarà sempre un multiplo di 1000 byte. Secondo me la cosa migliore da fare quando si tratta di scambiare file è di inviare prima la dimensione totale del file da scambiare e quindi salvare su file solo il numero di byte ke ti interessano. Ora non mi vengono in mente altre soluzioni più raffinate, ma sicuramente questa è la + semplice ed efficace ke mi è passata x la testa
__________________
|
|
|
|
|
|
#6 | |
|
Senior Member
Iscritto dal: Sep 2005
Città: Torino
Messaggi: 606
|
Quote:
mi stai forse dicendo che devo interrompere l'input del client quando faccio download e upload??? in effetti...pensandoci un pò...non può che essere questo il problema!!! però come posso farlo??? in ogni caso, grazie per la pazienza!
__________________
"Se proprio dovete piratare un prodotto, preferiamo che sia il nostro piuttosto che quello di qualcun altro." [Jeff Raikes] "Pirating software? Choose Microsoft!" |
|
|
|
|
|
|
#7 | |
|
Senior Member
Iscritto dal: Sep 2005
Città: Torino
Messaggi: 606
|
Quote:
(nota: il metodo int read(byte[] b) di FileInputStream ritorna il numero totale di byte letti nel buffer)
__________________
"Se proprio dovete piratare un prodotto, preferiamo che sia il nostro piuttosto che quello di qualcun altro." [Jeff Raikes] "Pirating software? Choose Microsoft!" |
|
|
|
|
|
|
#8 | |
|
Senior Member
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12112
|
Quote:
Per sbloccarlo e fargli ricavare il socket telnet inviandogli il carattere "invio". In questo modo il primo carattere del socket è il carattere invio. Quindi ti metti a ciclare per leggere il file, ma potrebbe capitare (non ho capito se è quello ke succede a te) ke ad ogni lettura di 1024 byte la tua classe resta in attesa di un altro carattere (dipende se il 1° byte viene consumato subito oppure no...ora non mi va di pensarci In quel caso ti potresti ritrovare il carattere nel mezzo del file. La soluzione migliore è ovviamente di utilizzare i thread, ma anche come ho fatto io, dividendo il programma in un client e un server tutto funziona ad hoc. In questo modo infatti il server sta in attesa fin quando il tuo client non si connette e inizia a mandare dati. Alla fine della trasmissione il server chiude la connessione (sempre se mi sono ricordato di aggiungere il socket.close()... ma ne dubito ).Le mie due classettine però hanno il problema che scrivono nel file sempre un buffer di 1000 char e quindi anke se il file originario è di un solo byte, quello di destinazione avrà dimensione 1000. Per ovviare a questo problema basta inviare come prima cosa la dimensione del file e quindi scrivere solo quel preciso numero di char (o di byte) nel file di destinazione. Cmq una cosa che devi assolutamente fare è dividere le logiche del client e del server perchè sennò non ci capisci niente in quel modo con l'invio e la ricezione concatenate
__________________
|
|
|
|
|
|
|
#9 |
|
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Ecco un esempio semplice semplice. Nota che è certamente migliorabile, principalmente nella gestione degli errori. Ma l'ho scritto velocemente perché stasera vado di fretta! Domani con calma lo aggiorno magari.
Compila e poi lancia: java FileServer 1234 e con un altro prompt java FileDownloader localhost 1234 Quando ti mostra >>> metti un path completo C:\blabla di un file e vedrai che te lo scarica nella directory dove sei.
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
|
|
|
|
|
#10 | |
|
Senior Member
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12112
|
Quote:
potresti anke fare in quel modo.. però.. non funziona Ora non ricordo bene il motivo, ma se non sbaglio mi aveva dato qualke problemino... O meglio. In locale e su rete LAN non da alcun problema se non erro.. ma quando ho provato ad usarlo col cellulare mediante UMTS mi ha iniziato a sbroccare di brutto ![]() Il problema se non erro era il carattere di chiusura del file.. nel senso che con le latenze dell'umts mi capitava che il socket non riceveva niente e qdi quando andavo a leggere mi ritrovavo un bel -1. Quindi l'ideale è vedere quant'è la dimensione totale del file e leggere fino a quel numero di byte. In questo modo avrai la sicurezza di aver ricevuto tutti i tuoi dati
__________________
|
|
|
|
|
|
|
#11 | ||
|
Senior Member
Iscritto dal: Sep 2005
Città: Torino
Messaggi: 606
|
Quote:
ora comunque provo le vostre classi e vediamo cosa salta fuori...tornerò (quasi sicuramente) a chiedere ulteriori consigli!! Quote:
grazie per le risposte.
__________________
"Se proprio dovete piratare un prodotto, preferiamo che sia il nostro piuttosto che quello di qualcun altro." [Jeff Raikes] "Pirating software? Choose Microsoft!" |
||
|
|
|
|
|
#12 | |
|
Senior Member
Iscritto dal: Sep 2005
Città: Torino
Messaggi: 606
|
Quote:
uff...ma a te funziona??a me si inchiodava FileDownloader appena entrato nel while...dopo aver stampato il nome del file che gli davo...poi ho pensato che forse il printwriter aveva bisogno di un flush...ora và...ma perchè mi assillano così tanto sti stream??e faccio girare il programma in locale ancora!!!non oso pensare cosa può succedere su una rete lenta... comunque grazie per il vostro tempo!
__________________
"Se proprio dovete piratare un prodotto, preferiamo che sia il nostro piuttosto che quello di qualcun altro." [Jeff Raikes] "Pirating software? Choose Microsoft!" |
|
|
|
|
|
|
#13 |
|
Senior Member
Iscritto dal: Sep 2005
Città: Torino
Messaggi: 606
|
Se metto insieme in una stessa classe il codice del client e del server succede che il file non lo copia ma stampa soltanto gli "invio" (i quadratini, ricordate?) che gli dò quando interrompe la lettura...ora non voorei dire fesserie ma credo che sia colpa del fatto che l'input stream del socket lo uso per:
1) colloquiare tra la classe (client+server) ed il telnet (client vero e proprio) 2) per leggere lo stream del socket dopo che c'ho scritto su una parte del file! come risolvo mantenendo sempre una sola classe??
__________________
"Se proprio dovete piratare un prodotto, preferiamo che sia il nostro piuttosto che quello di qualcun altro." [Jeff Raikes] "Pirating software? Choose Microsoft!" |
|
|
|
|
|
#14 | |
|
Senior Member
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12112
|
Quote:
lanci nel metodo run il server e nel flusso normale esegui il client.. ma è davvero sporchissima come soluzione ![]() Perchè vuoi x forza usare una sola classe? ![]() non ha alcun senso... anke xkè concettualmente Client e Server dovrebbero stare su macchine diverse
__________________
|
|
|
|
|
|
|
#15 | |
|
Senior Member
Iscritto dal: Sep 2005
Città: Torino
Messaggi: 606
|
Quote:
ho capito! Non riesco ad immaginarmi proprio bene il programma, ho tanta confusione in testa!! in effetti il vero client dovrebbe essere il telnet che si connette al server(ServerSocket)...però ho bisogno anche del client (Socket) che a quanto ho capito lo ottengo solo dall'accept() del server...inoltre da lato client vorrei avere solo il telnet e non una classe...!! hai suggerimenti?
__________________
"Se proprio dovete piratare un prodotto, preferiamo che sia il nostro piuttosto che quello di qualcun altro." [Jeff Raikes] "Pirating software? Choose Microsoft!" |
|
|
|
|
|
|
#16 | |
|
Senior Member
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12112
|
Quote:
mi sono perso ke te ne fai di telnet? Se lo usi per inviare comandi devi solo avere un server senza client ke accetti i comandi li parsifiki e faccia le operazioni ke vuoi.. ma senza una classe client ad esempio non potrai ricevere alcunkè dal server.. ma potrai solo eseguire appunto dei comandi da remoto... Se mi spieghi x bene cosa vuoi fare magari riesco anke ad esserti d'aiuto
__________________
|
|
|
|
|
|
|
#17 |
|
Senior Member
Iscritto dal: Sep 2005
Città: Torino
Messaggi: 606
|
mmm...sto alquanto fulminato eh??
ma non è sempre così giuro!!! allora ti dico cosa ho in mente così magari ti riesci a districare meglio nei miei pensieri!!! il server (o meglio lo chiamo programma A perchè così non sbaglio...) dovrebbe poter: 1) interpretare ed eseguire comandi inviati con il telnet(es: upload e download files; in generale i più importanti comandi del prompt..) 2) accettare connessioni multiple (non necessario) 3) redirezionare tutto l'output del server (tutto, anche gli errori) al client, magari su un file di log! assomiglia molto a una connessione di assistenza remota [edit] in effetti...pensandoci un pò a mente lucida (durerà poco la mia lucidità) posso benissimo lasciar stare il telnet e fare tutto con un client...giusto?
__________________
"Se proprio dovete piratare un prodotto, preferiamo che sia il nostro piuttosto che quello di qualcun altro." [Jeff Raikes] "Pirating software? Choose Microsoft!" Ultima modifica di Oceans11 : 14-12-2006 alle 10:39. |
|
|
|
|
|
#18 | |
|
Senior Member
Iscritto dal: Sep 2005
Città: Torino
Messaggi: 606
|
Quote:
l'unico problema è che così facendo devo portarmi a spasso e copiare sui computer che uso oltre che il server anche il client...mentre con telnet....beh ci sta già no?
__________________
"Se proprio dovete piratare un prodotto, preferiamo che sia il nostro piuttosto che quello di qualcun altro." [Jeff Raikes] "Pirating software? Choose Microsoft!" |
|
|
|
|
|
|
#19 | |
|
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Quote:
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
|
|
|
|
|
|
#20 |
|
Senior Member
Iscritto dal: Sep 2005
Città: Torino
Messaggi: 606
|
hai ragione e avevo capito...
quindi devo scegliere: 1) telnet come client ma niente download file dal server... 2) classe client con download file dal server ma no telnet...giusto?
__________________
"Se proprio dovete piratare un prodotto, preferiamo che sia il nostro piuttosto che quello di qualcun altro." [Jeff Raikes] "Pirating software? Choose Microsoft!" |
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 19:29.











).









