MokaByte
Numero 20 - Giugno 1998
|
|||
II parte |
|||
|
|
||
Dopo aver
paralto della teoria (nell'articolo precedente), e di come realizzare un
server ftp,
vediamo come
si implementa un client ftp.
Dopo tanto penare,
eccoci infine a vedere come si fa una semplice applicazione che gestisce
il protocollo FTP.
Questa applicazione
consentirà all’utente di loggarsi, inserendo UserName e Password,
disconnettersi, settare la modalità di trasferimento Files (Binaria
o ASCII), leggere la directory corrente, cambiarla, scaricare e uploadare
un file.
In pratica è
un completo sistema di FTP, magari un po’ “spartano” da usare, ma completo
di tutto quanto è fondamentale.
Bene, come avevo
detto l’altra volta, per prima cosa è necessario connettersi al
server alla porta 21.
Per fare questo
si usa questa parte di codice (che, bene o male, dovrebbe essere un sistema
abbastanza standard e conosciuto un po’ da tutti noi):
// Apertura Socket e inizializzazione degli Stream di Input e OutputQui, come si può notare, si apre il socket e si inizializzano gli Stream di Input e di Output.
ftpSocket=new Socket(Host,21);
os=new PrintStream(ftpSocket.getOutputStream());
is=new DataInputStream(ftpSocket.getInputStream());
ok=true;Questo ciclo attende dati dal server fino a che non dà un certo messaggio (questo varierà di volta in volta). In questo caso attende il 220, ossia “Bene, dimmi di chi sei”.
while(ok)
{
s=is.readLine();
System.out.println(s);
if(s.length()>5)
if(s.substring(0,4).compareTo("220 ")==0)
ok=false;
}
? ASCII
Imposta la modalità di trasferimento ASCII
? Binary
Imposta la modalità di trasferimento binaria
? Change
Directory Cambia la directory corrente
? Dir
Visualizza il contenuto della directory corrente
? Get File
Scarica un file
? Help
Visualizza l’Help
? Print
Directory Visualizza la directory corrente
? Store File
Spedisce un file
? Quit
Esce dal programma
Vediamo un attimino
due comandi (gli altri sono molto simili e lascio la semplice interpretazione
alla lettura del sorgente).
I comandi che
vedremo ora sono Change e Dir, che servono rispettivamente per cambiare
la directory corrente e per visualizzare la directory corrente.
Questi due comandi
hanno una grande differenza tra di loro. Il primo non ha un passaggio di
dati, una volta lanciato il comando si attende la risposta ed è
tutto finito li, il secondo invece ha anche un passaggio di dati che avviene,
come ho detto nello scorso articolo, tramite un socket diverso, aperto
sul momento e per questa funzione.
Gli altri comandi
sono simili a questi due e, per amor di cronaca, dirò che i comandi
ASCII, Binary, Print Directory e Quit sono uguali come funzionamento
al comando Change, mentre Get File e Store File sono uguali come funzionamento
al comando Dir.
Bene, cominciamo
dunque a vedere il più semplice, ossia il comando Change.
Il codice che
esegue questo comando è il seguente:
os.println("CWD "+Dir);Come si vede è decisamente banale. Si spedisce il comando (CWD + Directory) e si cicla attendendo la risposta (250=Tutto OK, 550=Directory inesistente).
ok=true;
while(ok)
{
s=is.readLine();
System.out.println(s);
if(s.length()>5)
if((s.substring(0,4).compareTo("250 ")==0) ||
(s.substring(0,4).compareTo("550 ")==0))
ok=false;
}
Vediamo ora il
comando più “complesso”, ossia il Dir.
Bene, come ho
già detto, è necessario aprire un secondo socket su una porta
diversa attraverso il quale passeranno i dati.
Bene, per prima
cosa dobbiamo comunicare al server l’indirizzo del proprio computer e la
porta sulla quale verrà aperto il socket.
Per fare questo
è necessario usare il comando PORT. Port richiede, come parametro,
l’indirizzo nel formato a,b,c,d e la porta, nel formato bh,bl. Il tutto
spedito assieme in questa maniera:
PORT a,b,c,d,bh,blPort ritorna come codice 200=OK! o 500=Porta non valida.
s1="";Come si vede la parte più onerosa in righe di codice è quella che contiene i cicli di attesa messaggi dal server. Questa parte è però fondamentale in quanto non si potrebbe altrimenti sapere se tutto è andato bene o meno.
H=ftpSocket.getInetAddress().getLocalHost().getHostAddress();
for(l=0;l<H.length();l++)
if(H.charAt(l)=='.')
s1+=',';
else
s1+=H.charAt(l);
P=GetPort();
// Manda la porta da usarsi
System.out.println("PORT "+s1+","+P);
os.println("PORT "+s1+","+P);
ok=true;
while(ok)
{
s=is.readLine();
System.out.println(s);
if(s.length()>5)
if((s.substring(0,4).compareTo("200 ")==0) ||
(s.substring(0,4).compareTo("500 ")==0))
ok=false;
}
if(s.substring(0,4).compareTo("200 ")==0)
{
// Apre il socket
Sck=new ServerSocket(NPort-1);
// Manda il comando
System.out.println("LIST");
os.println("LIST");
ok=true;
while(ok)
{
s=is.readLine();
System.out.println(s);
if(s.length()>5)
if((s.substring(0,4).compareTo("150 ")==0) ||
(s.substring(0,4).compareTo("425 ")==0))
ok=false;
}
if(s.substring(0,4).compareTo("150 ")==0)
{
// Se tutto è andato bene, visualizza i dati che arrivano dalla nuova porta
sck=Sck.accept();
isd=new DataInputStream(sck.getInputStream());
ok1=false;
s=isd.readLine();
System.out.println(s);
while(isd.available()!=0)
{
s=isd.readLine();
System.out.println(s);
}
ok=true;
while(ok)
{
s=is.readLine();
System.out.println(s);
if(s.length()>5)
if(s.substring(0,4).compareTo("226 ")==0)
ok=false;
}
sck.close();
}
Sck.close();
}
Concludo dunque
qui la mia breve dissertazione sul protocollo FTP. Come al solito, se qualcuno
necessita di spiegazioni non ha che da mandarmi una E-Mail e risponderò
volentieri.
L’uso del programma
è banale. Occorre lanciarlo dando come parametro l’host a cui collegarsi.
Il programma chiederà UserName e Password (naturalmente è
anche possibile anche la connessione anonima) e quindi visualizza l’help
e accetta i comandi.
Sorgente del programma FTP.java
import java.awt.*;
import java.io.*;
import java.net.*;public class ftp
{
public static DataInputStream is; // Stream di Input
public static PrintStream os; // Stream di Output
public static Socket ftpSocket; // Socket di comunicazione
public static int NPort; // Porta. Numero progressivo
public static String TrMode; // Transfer Mode. Ascii o Binary
public static char getch()
{
char c;// Questa procedura attende la pressione di un tasto.
c=0;
while(c==0)
try
{
c=(char) System.in.read();
}
catch(Exception e)
{
c=0;
}return(c);
}
public static int Comando(boolean vis)
{
char c=0;
boolean ok=true;try
{
while(System.in.available()!=0)
getch();
}
catch(Exception e)
{
}
// Schermata con l'elenco dei comandi disponibili.
// Attende che si prema un tasto e si immetta un comando.
if(vis)
{
System.out.println("Elenco comandi disponibili.");
System.out.println(" (A)SCII Imposta la modalita' di trasferimento ASCII");
System.out.println(" (B)inary Imposta la modalita' di trasferimento binaria");
System.out.println(" (C)hange Directory Cambia la directory corrente");
System.out.println(" (D)ir Visualizza il contenuto della directory corrente");
System.out.println(" (G)et File Scarica un file");
System.out.println(" (H)elp Visualizza questo Help");
System.out.println(" (P)rint Directory Visualizza la directory corrente");
System.out.println(" (S)tore File Spedisce un file");
System.out.println(" (Q)uit Esce dal programma");
System.out.println("Inserire un comando (C/D/H/P/S/Q): ");
}c=getch();
try
{
while(System.in.available()!=0)
getch();
}
catch(Exception e)
{
}c=Character.toUpperCase(c);
if((c=='Q') || (c=='C') || (c=='H') || (c=='D') || (c=='A') || (c=='B') || (c=='G') || (c=='P') || (c=='S'))
ok=false;return(c);
}
public static long atol(String s)
{
// Converte la string passato in un longLong tempInt;
String s1;
int l,k;
long q=0;for(l=-1,k=0;(k<s.length()) && (l==-1);k++)
if((s.charAt(k)<'0') || (s.charAt(k)>'9'))
l=k;if(l==-1)
{
s1=s;
tempInt = Long.valueOf(s1);
q=tempInt.longValue();
}
else
if(l!=0)
{
s1=s.substring(0,l);
tempInt = Long.valueOf(s1);
q=tempInt.longValue();
}return(q);
}
public static int atoi(String s)
{
// Converte la string passato in un integerInteger tempInt;
String s1;
int k,l;for(l=-1,k=0;(k<s.length()) && (l==-1);k++)
if((s.charAt(k)<'0') || (s.charAt(k)>'9'))
l=k;if(l==-1)
{
s1=s;
tempInt = Integer.valueOf(s1);
k=tempInt.intValue();
}
else
if(l!=0)
{
s1=s.substring(0,l);
tempInt = Integer.valueOf(s1);
k=tempInt.intValue();
}
else
k=0;return(k);
}
public static String GetString(String Prompt)
{
String s="",Ret="";
int n=0;
char c;// Prende una stringa da tastiera
System.out.print(Prompt+": ");
while(s.length()==0)
try
{
c=0;
while(c!='\n')
{
c=getch();
if(c!='\n')
s+=c;
}
}
catch(Exception e)
{
}Ret=s.substring(0,s.length()-1);
return(Ret);
}
public static boolean OpenComm() throws IOException
{
// Questa procedura si "logga" con il server, fornendo UserName e Password.
// Visualizza messaggi di errore nel caso UserName o Password siano errati
// Ritorna TRUE se si e' loggato, FALSE altrimentiString s="",User="",Passwd="";
boolean Ret=true,ok;ok=true;
while(ok)
{
s=is.readLine();
System.out.println(s);
if(s.length()>5)
if(s.substring(0,4).compareTo("220 ")==0)
ok=false;
}
User=GetString("UserName");
os.println("USER "+User);
System.out.println("USER "+User);
ok=true;
while(ok)
{
s=is.readLine();
System.out.println(s);
if(s.length()>5)
if(s.substring(0,4).compareTo("331 ")==0)
ok=false;
}
Passwd=GetString("Password");
os.println("PASS "+Passwd);
System.out.println("PASS ********");
ok=true;
while(ok)
{
s=is.readLine();
System.out.println(s);
if(s.length()>5)
if((s.substring(0,4).compareTo("230 ")==0) || (s.substring(0,4).compareTo("530 ")==0))
ok=false;
}
if(s.substring(0,4).compareTo("230 ")==0)
System.out.println("Utente "+User+" Connesso");
else
Ret=false;return(Ret);
}
public static void ChDir() throws IOException
{
String Dir,s="";
boolean ok;// Cambia la directory corrente
Dir=GetString("Nuova Directory");
os.println("CWD "+Dir);
// Ciclo di attesa messaggio dal server
ok=true;
while(ok)
{
s=is.readLine();
System.out.println(s);
if(s.length()>5)
if((s.substring(0,4).compareTo("250 ")==0) || (s.substring(0,4).compareTo("550 ")==0))
ok=false;
}
}
public static void PwDir() throws IOException
{
boolean ok;
String s="";// Visualizza la directory corrente
os.println("PWD");
// Ciclo di attesa messaggio dal server
ok=true;
while(ok)
{
s=is.readLine();
System.out.println(s);
if(s.length()>5)
if(s.substring(0,4).compareTo("257 ")==0)
ok=false;
}
}
public static String GetPort()
{
int l,h;
String R;// Scompone il numero di porta (progressivo) in Byte Alto e Byte Basso
h=NPort/256;
l=NPort-(h*256);
R=""+h+","+l;
NPort++;return(R);
}
public static void GetFile() throws IOException
{
boolean ok,ok1=true;
String s="",s1,P="",H="",NFile="",NFileS="";
int l;
ServerSocket Sck;
Socket sck;
DataInputStream isd;
RandomAccessFile f;// Scarica un file
NFile=GetString("File da scaricare");
NFileS=GetString("File scaricato");
// Cicla finchè il file è stato trasferito senza errori
while(ok1)
{
s1="";
H=ftpSocket.getInetAddress().getLocalHost().getHostAddress();
for(l=0;l<H.length();l++)
if(H.charAt(l)=='.')
s1+=',';
else
s1+=H.charAt(l);
P=GetPort();
// Imposta la porta
System.out.println("PORT "+s1+","+P);
os.println("PORT "+s1+","+P);
ok=true;
while(ok)
{
s=is.readLine();
System.out.println(s);
if(s.length()>5)
if((s.substring(0,4).compareTo("200 ")==0) || (s.substring(0,4).compareTo("500 ")==0))
ok=false;
}
if(s.substring(0,4).compareTo("200 ")==0)
{
// Imposta il tipo di file
System.out.println("TYPE "+TrMode);
os.println("TYPE "+TrMode);
ok=true;
while(ok)
{
s=is.readLine();
System.out.println(s);
if(s.length()>5)
if((s.substring(0,4).compareTo("200 ")==0) || (s.substring(0,4).compareTo("500 ")==0))
ok=false;
}
// Apre il nuovo socket
Sck=new ServerSocket(NPort-1);
// Manda il comando di download
System.out.println("RETR "+NFile);
os.println("RETR "+NFile);
ok=true;
while(ok)
{
s=is.readLine();
System.out.println(s);
if(s.length()>5)
if((s.substring(0,4).compareTo("150 ")==0) || (s.substring(0,4).compareTo("425 ")==0))
ok=false;
}
if(s.substring(0,4).compareTo("150 ")==0)
{
// Se tutto è andato bene, si prepara ad accettare i dati
sck=Sck.accept();
isd=new DataInputStream(sck.getInputStream());
f=new RandomAccessFile(NFileS,"rw");
ok1=false;
// Scrive i dati su disco
f.write(isd.read());
while(isd.available()!=0)
f.write(isd.read());
f.close();
ok=true;
while(ok)
{
s=is.readLine();
System.out.println(s);
if(s.length()>5)
if(s.substring(0,4).compareTo("226 ")==0)
ok=false;
}
sck.close();
}
Sck.close();
}
}
}
public static void PutFile() throws IOException
{
boolean ok,ok1=true;
String s="",s1,P="",H="",NFile="",NFileS="";
int l;
ServerSocket Sck;
Socket sck;
PrintStream osd;
RandomAccessFile f;// Procedure di upload
NFile=GetString("File da mandare");
NFileS=GetString("File remoto");
while(ok1)
{
s1="";
H=ftpSocket.getInetAddress().getLocalHost().getHostAddress();
for(l=0;l<H.length();l++)
if(H.charAt(l)=='.')
s1+=',';
else
s1+=H.charAt(l);
P=GetPort();
System.out.println("PORT "+s1+","+P);
os.println("PORT "+s1+","+P);
ok=true;
while(ok)
{
s=is.readLine();
System.out.println(s);
if(s.length()>5)
if((s.substring(0,4).compareTo("200 ")==0) || (s.substring(0,4).compareTo("500 ")==0))
ok=false;
}
if(s.substring(0,4).compareTo("200 ")==0)
{
System.out.println("TYPE "+TrMode);
os.println("TYPE "+TrMode);
ok=true;
while(ok)
{
s=is.readLine();
System.out.println(s);
if(s.length()>5)
if((s.substring(0,4).compareTo("200 ")==0) || (s.substring(0,4).compareTo("500 ")==0))
ok=false;
}
System.out.println("STOR "+NFile);
os.println("STOR "+NFile);
Sck=new ServerSocket(NPort-1);
ok=true;
while(ok)
{
s=is.readLine();
System.out.println(s);
if(s.length()>5)
if((s.substring(0,4).compareTo("150 ")==0) || (s.substring(0,4).compareTo("425 ")==0))
ok=false;
}
if(s.substring(0,4).compareTo("150 ")==0)
{
sck=Sck.accept();
osd=new PrintStream(sck.getOutputStream());
f=new RandomAccessFile(NFileS,"r");
ok1=false;
while(f.getFilePointer()<f.length())
osd.write(f.read());
f.close();
sck.close();
ok=true;
while(ok)
{
s=is.readLine();
System.out.println(s);
if(s.length()>5)
if(s.substring(0,4).compareTo("226 ")==0)
ok=false;
}
}
Sck.close();
}
}
}
public static void GetDir() throws IOException
{
boolean ok,ok1;
String s="",s1,P="",H="";
int l;
ServerSocket Sck;
Socket sck;
DataInputStream isd;// Visualizza il contenuto della directory corrente
ok1=true;
while(ok1)
{
s1="";
H=ftpSocket.getInetAddress().getLocalHost().getHostAddress();
for(l=0;l<H.length();l++)
if(H.charAt(l)=='.')
s1+=',';
else
s1+=H.charAt(l);
P=GetPort();
// Manda la porta da usarsi
System.out.println("PORT "+s1+","+P);
os.println("PORT "+s1+","+P);
ok=true;
while(ok)
{
s=is.readLine();
System.out.println(s);
if(s.length()>5)
if((s.substring(0,4).compareTo("200 ")==0) || (s.substring(0,4).compareTo("500 ")==0))
ok=false;
}
if(s.substring(0,4).compareTo("200 ")==0)
{
// Apre il socket
Sck=new ServerSocket(NPort-1);
// Manda il comando
System.out.println("LIST");
os.println("LIST");
ok=true;
while(ok)
{
s=is.readLine();
System.out.println(s);
if(s.length()>5)
if((s.substring(0,4).compareTo("150 ")==0) || (s.substring(0,4).compareTo("425 ")==0))
ok=false;
}
if(s.substring(0,4).compareTo("150 ")==0)
{
// Se tutto è andato bene, visualizza i dati che arrivano dalla nuova porta
sck=Sck.accept();
isd=new DataInputStream(sck.getInputStream());
ok1=false;
s=isd.readLine();
System.out.println(s);
while(isd.available()!=0)
{
s=isd.readLine();
System.out.println(s);
}
ok=true;
while(ok)
{
s=is.readLine();
System.out.println(s);
if(s.length()>5)
if(s.substring(0,4).compareTo("226 ")==0)
ok=false;
}
sck.close();
}
Sck.close();
}
}
}
public static void SetTrMode(String Mod) throws IOException
{
String s="";
boolean ok;// Imposta la modalità di trasferimento file.
// A=ASCII
// I=Binary
TrMode=Mod;
os.println("TYPE "+Mod);
System.out.println("TYPE "+Mod);
ok=true;
while(ok)
{
s=is.readLine();
System.out.println(s);
if(s.length()>5)
if(s.substring(0,4).compareTo("200 ")==0)
ok=false;
}
}
public static void Connect(String Host) throws IOException
{
boolean ok=true,vis=true;
String s="";
int c,n;// Apertura Socket e inizializzazione degli Stream di Input e Output
ftpSocket=new Socket(Host,21);
os=new PrintStream(ftpSocket.getOutputStream());
is=new DataInputStream(ftpSocket.getInputStream());
NPort=50000;// Se l'utente e' loggato correttamente, accetta i comandi
if(OpenComm()==true)
{
// Ciclo finchè non si decide di uscire.
// Prende l'istruzione dall'utente e la esegue.
while(ok)
{
c=Comando(vis);
vis=false;
switch(c)
{
case 'A':
SetTrMode("A");
break;
case 'B':
SetTrMode("I");
break;
case 'G':
GetFile();
break;
case 'H':
vis=true;
break;
case 'C':
ChDir();
break;
case 'D':
GetDir();
break;
case 'P':
PwDir();
break;
case 'S':
PutFile();
break;
case 'Q':
ok=false;
break;
}
}
}// Chiude la comunicazione con FTP e si disconnette
os.println("QUIT");
System.out.println("QUIT");
ok=true;
while(ok)
{
s=is.readLine();
System.out.println(s);
if(s.length()>5)
if(s.substring(0,4).compareTo("221 ")==0)
ok=false;
}is.close();
os.close();
ftpSocket.close();
}public static void main(String args[])
{
try
{
Connect(args[0]);
}
catch(Exception e)
{
System.out.println("Eccezione "+e);
}
}
}
MokaByte Web 1998 - www.mokabyte.it MokaByte ricerca nuovi collaboratori. Chi volesse mettersi in contatto con noi può farlo scrivendo a mokainfo@mokabyte.it |