Oceans11
29-05-2007, 20:28
Stavo pensando a come scrivere un client ftp in java, inizialmente da riga di comando e poi magari con gui (dico magari perchè ho seri problemi di integrazione tra programma e gui! :muro: )
Ho scaricato le rfc relative al protocollo per vedere com'è fatto e conoscere i codici di controllo/errore, piano piano le leggo! :D
mi potete dare qualche consiglio o dritta sulla progettazione?purtroppo il mio più grande problema è che mi ci perdo, idem con la scelta delle varie classi!mentre ad alcuni di voi viene naturale!
ciao!
Mentre aspettiamo qualcuno a cui la progettazione viene naturale, potresti iniziare...dalla fine :D.
Vesti i panni del programmatore che vuole usare le librerie che devi creare. Sii pigro. Se vuoi inviare un file allora vuoi farlo dicendo:
client.apri()
client.invia(file);
client.chiudi();
Ma sarebbe meglio il pigerrimo:
client.invia(file);
Si può fare? Probabilmente no. A chi lo mandi. Allora dovrai dire una cosa tipo:
client.inviaFileA(file, indirizzoFtp);
E se volessi interrompere li trasferimento? Be', potremmo dire:
FTPTransfer transfer = client.inviaFileA(file, indirizzoFTP);
e, alla bisogna,
transfer.stop();
Ciò significherebbe fare di client.inviaFileA un Future. Un FTPTransfer potrebbe avere degli FTPTransferListener a cui l'FTPTransfer comunicherebbe, che so, l'inizio, il prosieguo ed il termine delle operazioni di trasferimento.
Sarebbe comodo per l'interfaccia utente. Vuoi sparare il file sul server? client.inviaFileA, aggiungi un listener all'FTPTransfer restituito e lo usi sia per far vedere all'utente il corso del trasferimento, sia per consentirgli di interromperlo.
Sfrugulliamenti simili si possono fare anche a livello di traduzione del protocollo.
Insomma, il mio suggerimento è: pensa pigro.
...ciao...
...ecco una classe ftp...prendi spunto...
import java.io.*;
import java.net.*;
import java.util.*;
public class Ftp extends Object {
private static boolean PRINT_DEBUG_INFO = false;
private Socket connectionSocket = null;
private PrintStream outputStream = null;
private BufferedReader inputStream = null;
private long restartPoint = 0L;
private boolean loggedIn = false;
public String lineTerm = "\n";
private static int BLOCK_SIZE = 4096;
public Ftp ()
{
System.out.println("Ftp Handler");
}
public Ftp (boolean debugOut)
{
PRINT_DEBUG_INFO = debugOut;
}
private void debugPrint(String message) {
if (PRINT_DEBUG_INFO) System.err.println(message);
}
public boolean connect(String host)
throws UnknownHostException, IOException
{
return connect(host, 21);
}
public boolean connect(String host, int port)
throws UnknownHostException, IOException
{
connectionSocket = new Socket(host, port);
outputStream = new PrintStream(connectionSocket.getOutputStream());
inputStream = new BufferedReader(new
InputStreamReader(connectionSocket.getInputStream()));
if (!isPositiveCompleteResponse(getServerReply())){
disconnect();
return false;
}
return true;
}
public void disconnect()
{
if (outputStream != null) {
try {
if (loggedIn) { logout(); };
outputStream.close();
inputStream.close();
connectionSocket.close();
} catch (IOException e) {}
outputStream = null;
inputStream = null;
connectionSocket = null;
}
}
public boolean login(String username, String password)
throws IOException
{
int response = executeCommand("user " + username);
if (!isPositiveIntermediateResponse(response)) return false;
response = executeCommand("pass " + password);
loggedIn = isPositiveCompleteResponse(response);
return loggedIn;
}
public boolean logout()
throws IOException
{
int response = executeCommand("quit");
loggedIn = !isPositiveCompleteResponse(response);
return !loggedIn;
}
public boolean changeDirectory(String directory)
throws IOException
{
int response = executeCommand("cwd " + directory);
return isPositiveCompleteResponse(response);
}
public boolean renameFile(String oldName, String newName)
throws IOException
{
int response = executeCommand("rnfr " + oldName);
if (!isPositiveIntermediateResponse(response)) return false;
response = executeCommand("rnto " + newName);
return isPositiveCompleteResponse(response);
}
public boolean makeDirectory(String directory)
throws IOException
{
int response = executeCommand("mkd " + directory);
return isPositiveCompleteResponse(response);
}
public boolean removeDirectory(String directory)
throws IOException
{
int response = executeCommand("rmd " + directory);
return isPositiveCompleteResponse(response);
}
public boolean parentDirectory()
throws IOException
{
int response = executeCommand("cdup");
return isPositiveCompleteResponse(response);
}
public boolean deleteFile(String fileName)
throws IOException
{
int response = executeCommand("dele " + fileName);
return isPositiveCompleteResponse(response);
}
public String getCurrentDirectory()
throws IOException
{
String response = getExecutionResponse("pwd");
StringTokenizer strtok = new StringTokenizer(response);
// Get rid of the first token, which is the return code
if (strtok.countTokens() < 2) return null;
strtok.nextToken();
String directoryName = strtok.nextToken();
// Most servers surround the directory name with quotation marks
int strlen = directoryName.length();
if (strlen == 0) return null;
if (directoryName.charAt(0) == '\"') {
directoryName = directoryName.substring(1);
strlen--;
}
if (directoryName.charAt(strlen - 1) == '\"')
return directoryName.substring(0, strlen - 1);
return directoryName;
}
public String getSystemType()
throws IOException
{
return excludeCode(getExecutionResponse("syst"));
}
public long getModificationTime(String fileName)
throws IOException
{
String response = excludeCode(getExecutionResponse("mdtm " + fileName));
try {
return Long.parseLong(response);
} catch (Exception e) {
return -1L;
}
}
public long getFileSize(String fileName)
throws IOException
{
String response = excludeCode(getExecutionResponse("size " + fileName));
try {
return Long.parseLong(response);
} catch (Exception e) {
return -1L;
}
}
public boolean downloadFile(String fileName)
throws IOException
{
return readDataToFile("retr " + fileName, fileName);
}
public boolean downloadFile(String serverPath, String localPath)
throws IOException
{
return readDataToFile("retr " + serverPath, localPath);
}
public boolean uploadFile(String fileName)
throws IOException
{
return writeDataFromFile("stor " + fileName, fileName);
}
public boolean uploadFile(String serverPath, String localPath)
throws IOException
{
return writeDataFromFile("stor " + serverPath, localPath);
}
public void setRestartPoint(int point)
{
restartPoint = point;
debugPrint("Restart noted");
}
private int getServerReply()
throws IOException
{
return Integer.parseInt(getFullServerReply().substring(0, 3));
}
private String getFullServerReply()
throws IOException
{
String reply;
do {
reply = inputStream.readLine();
debugPrint(reply);
} while(!(Character.isDigit(reply.charAt(0)) &&
Character.isDigit(reply.charAt(1)) &&
Character.isDigit(reply.charAt(2)) &&
reply.charAt(3) == ' '));
return reply;
}
private String getFullServerReply(StringBuffer fullReply)throws IOException
{
String reply;
fullReply.setLength(0);
do {
reply = inputStream.readLine();
debugPrint(reply);
fullReply.append(reply + lineTerm);
} while(!(Character.isDigit(reply.charAt(0)) &&
Character.isDigit(reply.charAt(1)) &&
Character.isDigit(reply.charAt(2)) &&
reply.charAt(3) == ' '));
// remove any trailing line terminators from the fullReply
if (fullReply.length() > 0)
{
fullReply.setLength(fullReply.length() - lineTerm.length());
}
return reply;
}
public String listFiles()
throws IOException
{
return listFiles("");
}
public String listFiles(String params)
throws IOException
{
StringBuffer files = new StringBuffer();
StringBuffer dirs = new StringBuffer();
if (!getAndParseDirList(params, files, dirs))
{
debugPrint("Error getting file list");
}
return files.toString();
}
public String listSubdirectories()
throws IOException
{
return listSubdirectories("");
}
public String listSubdirectories(String params)
throws IOException
{
StringBuffer files = new StringBuffer();
StringBuffer dirs = new StringBuffer();
if (!getAndParseDirList(params, files, dirs))
{
debugPrint("Error getting dir list");
}
return dirs.toString();
}
private String processFileListCommand(String command)
throws IOException
{
StringBuffer reply = new StringBuffer();
String replyString;
// file listings require you to issue a PORT command,
// like a file transfer
boolean success = executeDataCommand(command, reply);
if (!success)
{
return "";
}
replyString = reply.toString();
// strip the trailing line terminator from the reply
if (reply.length() > 0)
{
return replyString.substring(0, reply.length() - 1);
} else {
return replyString;
}
}
private boolean getAndParseDirList(String params, StringBuffer files, StringBuffer dirs)
throws IOException
{
// reset the return variables (we're using StringBuffers instead of
// Strings because you can't change a String value and pass it back
// to the calling routine -- changing a String creates a new object)
files.setLength(0);
dirs.setLength(0);
// get the NLST and the LIST -- don't worry if the commands
// don't work, because we'll just end up sending nothing back
// if that's the case
String shortList = processFileListCommand("nlst " + params);
String longList = processFileListCommand("list " + params);
// tokenize the lists we got, using a newline as a separator
StringTokenizer sList = new StringTokenizer(shortList, "\n");
StringTokenizer lList = new StringTokenizer(longList, "\n");
// other variables we'll need
String sString;
String lString;
// assume that both lists have the same number of elements
while ((sList.hasMoreTokens()) && (lList.hasMoreTokens())) {
sString = sList.nextToken();
lString = lList.nextToken();
if (lString.length() > 0)
{
if (lString.startsWith("d"))
{
dirs.append(sString.trim() + lineTerm);
debugPrint("Dir: " + sString);
} else if (lString.startsWith("-")) {
files.append(sString.trim() + lineTerm);
debugPrint("File: " + sString);
} else {
// actually, symbolic links will start with an "l"
// (lowercase L), but we're not going to mess with
// those
debugPrint("Unknown: " + lString);
}
}
}
// strip off any trailing line terminators and return the values
if (files.length() > 0) { files.setLength(files.length() - lineTerm.length()); }
if (dirs.length() > 0) { dirs.setLength(dirs.length() - lineTerm.length()); }
return true;
}
public int executeCommand(String command)
throws IOException
{
outputStream.println(command);
return getServerReply();
}
public String getExecutionResponse(String command)
throws IOException
{
outputStream.println(command);
return getFullServerReply();
}
public boolean readDataToFile(String command, String fileName)
throws IOException
{
// Open the local file
RandomAccessFile outfile = new RandomAccessFile(fileName, "rw");
// Do restart if desired
if (restartPoint != 0) {
debugPrint("Seeking to " + restartPoint);
outfile.seek(restartPoint);
}
// Convert the RandomAccessFile to an OutputStream
FileOutputStream fileStream = new FileOutputStream(outfile.getFD());
boolean success = executeDataCommand(command, fileStream);
outfile.close();
return success;
}
public boolean writeDataFromFile(String command, String fileName)
throws IOException
{
// Open the local file
RandomAccessFile infile = new RandomAccessFile(fileName, "r");
// Do restart if desired
if (restartPoint != 0) {
debugPrint("Seeking to " + restartPoint);
infile.seek(restartPoint);
}
// Convert the RandomAccessFile to an InputStream
FileInputStream fileStream = new FileInputStream(infile.getFD());
boolean success = executeDataCommand(command, fileStream);
infile.close();
return success;
}
public boolean executeDataCommand(String command, OutputStream out)
throws IOException
{
// Open a data socket on this computer
ServerSocket serverSocket = new ServerSocket(0);
if (!setupDataPort(command, serverSocket)) return false;
Socket clientSocket = serverSocket.accept();
// Transfer the data
InputStream in = clientSocket.getInputStream();
transferData(in, out);
// Clean up the data structures
in.close();
clientSocket.close();
serverSocket.close();
return isPositiveCompleteResponse(getServerReply());
}
public boolean executeDataCommand(String command, InputStream in)
throws IOException
{
// Open a data socket on this computer
ServerSocket serverSocket = new ServerSocket(0);
if (!setupDataPort(command, serverSocket)) return false;
Socket clientSocket = serverSocket.accept();
// Transfer the data
OutputStream out = clientSocket.getOutputStream();
transferData(in, out);
// Clean up the data structures
out.close();
clientSocket.close();
serverSocket.close();
return isPositiveCompleteResponse(getServerReply());
}
public boolean executeDataCommand(String command, StringBuffer sb)
throws IOException
{
// Open a data socket on this computer
ServerSocket serverSocket = new ServerSocket(0);
if (!setupDataPort(command, serverSocket)) return false;
Socket clientSocket = serverSocket.accept();
// Transfer the data
InputStream in = clientSocket.getInputStream();
transferData(in, sb);
// Clean up the data structures
in.close();
clientSocket.close();
serverSocket.close();
return isPositiveCompleteResponse(getServerReply());
}
private void transferData(InputStream in, OutputStream out)
throws IOException
{
byte b[] = new byte[BLOCK_SIZE];
int amount;
// Read the data into the file
while ((amount = in.read(b)) > 0) {
out.write(b, 0, amount);
}
}
private void transferData(InputStream in, StringBuffer sb)
throws IOException
{
byte b[] = new byte[BLOCK_SIZE];
int amount;
// Read the data into the StringBuffer
while ((amount = in.read(b)) > 0) {
sb.append(new String(b, 0, amount));
}
}
private boolean setupDataPort(String command, ServerSocket serverSocket)
throws IOException
{
// Send our local data port to the server
if (!openPort(serverSocket)) return false;
// Set binary type transfer
outputStream.println("type i");
if (!isPositiveCompleteResponse(getServerReply())) {
debugPrint("Could not set transfer type");
return false;
}
// If we have a restart point, send that information
if (restartPoint != 0) {
outputStream.println("rest " + restartPoint);
restartPoint = 0;
// TODO: Interpret server response here
getServerReply();
}
// Send the command
outputStream.println(command);
return isPositivePreliminaryResponse(getServerReply());
}
private boolean openPort(ServerSocket serverSocket)
throws IOException
{
int localport = serverSocket.getLocalPort();
// get local ip address
InetAddress inetaddress = serverSocket.getInetAddress();
InetAddress localip;
try {
localip = InetAddress.getLocalHost();
} catch(UnknownHostException e) {
debugPrint("Can't get local host");
return false;
}
// get ip address in high byte order
byte[] addrbytes = localip.getAddress();
// tell server what port we are listening on
short addrshorts[] = new short[4];
// problem: bytes greater than 127 are printed as negative numbers
for(int i = 0; i <= 3; i++) {
addrshorts[i] = addrbytes[i];
if (addrshorts[i] < 0)
addrshorts[i] += 256;
}
outputStream.println("port " + addrshorts[0] + "," + addrshorts[1] +
"," + addrshorts[2] + "," + addrshorts[3] + "," +
((localport & 0xff00) >> 8) + "," +
(localport & 0x00ff));
return isPositiveCompleteResponse(getServerReply());
}
private boolean isPositivePreliminaryResponse(int response)
{
return (response >= 100 && response < 200);
}
private boolean isPositiveIntermediateResponse(int response)
{
return (response >= 300 && response < 400);
}
private boolean isPositiveCompleteResponse(int response)
{
return (response >= 200 && response < 300);
}
private boolean isTransientNegativeResponse(int response)
{
return (response >= 400 && response < 500);
}
private boolean isPermanentNegativeResponse(int response)
{
return (response >= 500 && response < 600);
}
private String excludeCode(String response)
{
if (response.length() < 5) return response;
return response.substring(4);
}
}
...ciao...
Oceans11
30-05-2007, 08:31
Insomma, il mio suggerimento è: pensa pigro.
cavolo questo mi riesce facile!!! grazie mille per i consigli...al di là del client ftp! :D
Oceans11
30-05-2007, 08:44
oh naturalmente i ringraziamenti sono anche per ally!! :D
una ulteriore domanda...che stream uso? byte, char o entrambi? stavo pensando a due tipi di connessione: raw e normale...che ne dite? e nel caso come le gestisco?? separatamente oppure ogni connessione normale si appoggia ad una raw?
oppure sto esagerando con lo sfarfugliamento? :D
manneshow
05-03-2009, 09:55
Io devo fare la stessa cosa in C.... sapresti consigliarmi qualche esempio??
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.