View Full Version : [Java] Problema ciclo
Ciao ragazzi devo fare un client FTP rudimentale utilizzando il Socket e devo implementare 2 funzioni a mia scelta .
Se provate a connetervi per esempio all'indirizzo ftp di altervista (es. idnob.altervista.org alla porta 21), il server vi manderà 5 messaggi di tipo 220 (una specie di ok) , ebbene io voglio leggere e metterli in output per poi procedere con il codice di login , la situazione è questa :
while ((mess = br.readLine()) != null) {
System.out.println(mess);
}
Dopodichè procederei con il codice per loggare l'utente :
System.out.print("Username : ");
user = brl.readLine();
pw.println("USER "+user); //Invio User
mess = br.readLine(); //ricezione if if(!mess.startsWith("331 ")) { System.out.println("Errore User");}
Poi c'è un altro pezzo simile per la password .
Riesco a vedere tutto quello che mi manda , il problema è che non riesco ad uscire da quel while per eseguire le istruzioni successive .
Se magari avete un terminale da cui lanciate FTP magari capite meglio .
Grazie mille in anticipo!
Prendilo con le pinze, ma sto sparando a caso, sicuro che lo stream termini?
Ma il tipo di questi 5 pacchetti iniziali è sempre lo stesso?
banryu79
08-09-2010, 14:55
Riesco a vedere tutto quello che mi manda , il problema è che non riesco ad uscire da quel while per eseguire le istruzioni successive .
Se magari avete un terminale da cui lanciate FTP magari capite meglio .
Grazie mille in anticipo!
Io ho provato questo:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;
/**
* host: idnob.altervista.org
* port: 21
*/
public class SocketFTP
{
public static void main(String[] args) throws IOException {
// establish a connection
String host = "idnob.altervista.org";
int port = 21;
Socket ftp = connectOrDie(host, port);
System.out.println("Connection accepted.");
BufferedReader in = getInputOrDie(ftp);
System.out.println("Input stream opened.");
String mess = null;
int count = 1;
while ((mess = in.readLine()) != null) {
System.out.println(count+"> "+mess);
count++;
}
System.out.println("Messaggio di benvenuto dal server: ricevuto.");
// close resorces:
// first close the streams THEN the socket
in.close();
ftp.close();
}
private static Socket connectOrDie(String host, int port) {
Socket socket = null;
try {
socket = new Socket(host, port);
} catch (UnknownHostException e) {
System.err.println("Don't know about host: "+host);
System.exit(1);
} catch (IOException e) {
System.err.println("an I/O error occurs when creating the socket");
System.exit(1);
}
return socket;
}
private static BufferedReader getInputOrDie(Socket socket) {
BufferedReader in = null;
try {
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
} catch (IOException e) {
System.err.println("Couldn't get input stream for the connection");
System.exit(1);
}
return in;
}
}
e questo è l'output che mi stampa:
Connection accepted.
Input stream opened.
1> 220---------- AlterVista FTP, based on Pure-FTPd [privsep] ----------
2> 220-Sei l'utente numero 10 di 80 consentiti
3> 220-L'ora locale � 15:56. Porta del server: 21.
4> 220-Questo � un sistema privato - Nessun login anonimo
5> 220 Sarai disconnesso dopo 5 minuti di inattivit�.
e poi rimane a girare... sembra sì che il ciclo non termini.
Penso sia un problema di charset... non a caso esistono librerie di terze parti che implementato il protocollo FTP.
Nella libreria standard di Java per l'FTP la classe java.net.URL può servire per qualche operazione, ma è più che altro Http-centrica. Per questo si ricorre a librerie esterne.
Quindi, anche se devi implementare solo 2 comandi del protocollo FTP, dato che devi comunque connetterti ad
un server arbitrario, tutta la parte di iniziale di connessione e parsing del messaggio di risposta del server deve
funzionare: devi supportare il riconoscimento del corretto charset.
Potresti provare a scaricarti un paio di librerie di terze parti, distribuite con i sorgenti, e spulciare cosa combinano
a proposito della scelta del giusto charset.
Se hai un IDE meglio: ti crei un progetto, importi la libreria da esaminare, e chiami il metodo connect o analogo della
classe che implementa l'FTP client (e quasi sempre si chiama proprio FTPClient).
A quel punto, l'IDE diventa comodo nel momento in cui ti fornisce la possibilità di cliccare sui nomi dei metodi come se fossero dei link (ad esempio in Netbeans con CTRL+Clik) da seguire e farti saltare su e giù per il codice seguendo il flusso del sorgente e dandoti la possibilità di leggere cosa entra in gioco, dove e come.
Da fare avendo sempre accanto una pagina del browser aperta sul documento rfc-959 ;)
si infatti il ciclo non termina perchè il controllo ce l'ha in pugno la br.readLine(); che non lo molla , secondo voi possiamo visualizzare i messaggi in un altro modo ?
@ Banryu
Hai capito in pieno ciò che devo fare il primo direi :)
@ oNaSsIs
Si sono 5 stringhe
Gentilissimi ragazzi , chiedo aiuto :)
banryu79
08-09-2010, 16:17
@Edit: mi correggo, non è un problema di charset (infatti le 5 righe del testo del messaggio di benvenuto le leggiamo) quanto di un bug noto (purtroppo) del metodo readLine di BufferedReader, che in certi casi non legge la fine dello stream, vedi:
qua (http://bugs.sun.com/bugdatabase/view_bug.do;jsessionid=f1de6c9b3fe8bbcd145bb461611?bug_id=4080163)e qua (http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4329985).
ok, capito , grazie mille per la segnalazione , e quindi secondo voi potrei usare un altro oggetto per leggere lo stream da socket che però " veda che il server non ha più niente da mandarmi" .
Grazie mille per la pazienza ragazzi.
khelidan1980
08-09-2010, 20:38
@Edit: mi correggo, non è un problema di charset (infatti le 5 righe del testo del messaggio di benvenuto le leggiamo) quanto di un bug noto (purtroppo) del metodo readLine di BufferedReader, che in certi casi non legge la fine dello stream, vedi:
qua (http://bugs.sun.com/bugdatabase/view_bug.do;jsessionid=f1de6c9b3fe8bbcd145bb461611?bug_id=4080163)e qua (http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4329985).
alla faccia della priority low :asd:
banryu79
09-09-2010, 15:09
Mi correggo: ho sbagliato di brutto, Java e la sua libreria non c'entrano una mazza, sono io che non funziono :asd:
Il vero problema (giuro, questa è l'ultima, lo azzecco :D) è che bisogna conoscere e rispettare il protocollo della comunicazione.
Nel nostro caso, la connessione di comunicazione del protocollo FTP segue, in linea di massima, le regole del protocollo Telnet. Questo in generale.
Nel nostro caso specifico, quando leggiamo una risposta dal server FTP, dobbiamo sapere in anticipo "quanto" c'è da leggere, perchè giustamente il server, finchè non gli chiediamo di chiudere la connessione cone il comando QUIT, lui non la chiude e l'inputStream rimane aperto con la conseguenza che il nostro ciclo di readLine() la sopra per forza di cose rimane in attesa di leggere una nuova linea sullo stream.
Per farla breve, ecco la regola:
Una response ftp è formata da un response code di tre cifre, e di un testo. Il server può rispondere con una singola linea, oppure con più linee.
Se la risposta è formata da una più linee allora ogni linea viene ripetuto il response code della risposta e il carattere che lo segue è un hypen ('-').
Nell'ultima riga invece il carattere che segue il response code è uno spazio.
Forti di questa conoscenza, correggiamo così:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
/**
* host: idnob.altervista.org
* port: 21
*/
public class SocketFTP
{
public static void main(String[] args) throws IOException {
String host = "idnob.altervista.org";
int port = 21;
// establish a connection
Socket ftp = connectOrDie(host, port);
BufferedReader in = getInputOrDie(ftp, "UTF-8");
// read response
String mess = null;
do {
mess = in.readLine();
System.out.println(mess);
} while (hasNextLine(mess));
System.out.println("Messaggio di benvenuto dal server: ricevuto.");
// close resorces:
// first close the streams THEN the socket
in.close();
ftp.close();
}
private static Socket connectOrDie(String host, int port) {
Socket socket = null;
try {
socket = new Socket(host, port);
} catch (UnknownHostException e) {
System.err.println("Don't know about host: "+host);
System.exit(1);
} catch (IOException e) {
System.err.println("an I/O error occurs when creating the socket");
System.exit(1);
}
return socket;
}
private static BufferedReader getInputOrDie(Socket socket, String charset) {
BufferedReader in = null;
try {
in = new BufferedReader(new InputStreamReader(socket.getInputStream(), charset));
} catch (IOException e) {
System.err.println("Couldn't get input stream for the connection");
System.exit(1);
}
return in;
}
private static boolean hasNextLine(String line) {
// we assume the response code (3 digits number) always
// occupies the first three chars of the line.
// If the fourth char is a hypen ('-') then the server has
// sent another line for us to read.
return line.charAt(3) == '-';
}
}
Ed ecco che succede quel che ci si attendeva.
220---------- AlterVista FTP, based on Pure-FTPd [privsep] ----------
220-Sei l'utente numero 8 di 80 consentiti
220-L'ora locale � 15:57. Porta del server: 21.
220-Questo � un sistema privato - Nessun login anonimo
220 Sarai disconnesso dopo 5 minuti di inattivit�.
Messaggio di benvenuto dal server: ricevuto.
Ottimo grandissimo , scusa se ho letto solo adesso ( non mi è arrivata la mail di notifica nuovo post) nel frattempo (stamattina) ho risolto usando il metodo ready(); del bufferedReader , che mi dice se lo strem successivo è bloccante , se lo è allora da false e procedo con il login , però rimango con le antenne alzate perchè dopo il login dovrò eseguire i primi comandi .
Nel frattempo GRAZIE MILLE A TUTTI !:D
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.