I am trying to use a socket to connect to a FTP site. Everything is fine, except that sometimes, when I try to run multiple RETR commands through the socket to download an entire directory, It most of the time freezes the program. Sometimes it actually will complete. I have a feeling it is a Buffered Reader problem. I am using a Buffered Reader to do the reading and It always seems to get stuck at the same place and I have been changing things for over a week now and i can't figure this out. Here is the code and I will add a comment to where it is getting stuck (it is in the waitForResponse() method. If you have any other comments on how I am trying to write this program I would like to hear them too. Thank you.
import java.io.*;
import java.net.Socket;
import java.util.StringTokenizer;
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
// This class extends Socket and is designed specifically be used
// for ftp connections only
//***********************************************************************************
public class FuriousFTPSocket{
// fields
//*****************************************************************************
private Socket socket = null;
private BufferedReader reader = null;
private BufferedWriter writer = null;
private String log = "";
private BufferedInputStream infoInput = null;
private Timer keepAliveTimer = new Timer(60000,
new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
try
{
sendCommand("NOOP", false);
waitForResponse(false);
}
catch(IOException ioe)
{
System.out.println("Could not keep connection alive.");
ioe.printStackTrace();
}
}
});
// Creates a FuriousFTP Object
//**********************************************************************************
public FuriousFTPSocket() {
}
// Connects to the default port of an FTP server and logs in as
// anonymous/anonymous.
//**********************************************************************************
public synchronized void connect(String host, boolean sendToLog) throws IOException {
connect(host, 21, sendToLog);
}
// Connects to an FTP server on the given port and logs in as
// anonymous/anonymous.
//**********************************************************************************
public synchronized void connect(String host, int port, boolean sendToLog) throws IOException {
connect(host, port, "anonymous", "anonymous", sendToLog);
}
// Connects to an FTP server on the given port and logs in with the supplied
// username and password.
//**********************************************************************************
public synchronized void connect(String host, int port, String user,
String pass, boolean sendToLog) throws IOException
{
if (socket != null)
{
if(sendToLog) addToLog("FuriousFTP is already connected.");
}
else
{
socket = new Socket(host, port);
//infoInput = new BufferedInputStream(socket.getInputStream());
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
String response = waitForResponse(sendToLog);
if (!response.startsWith("220")) {
throw new IOException(
"FuriousFTP received an unknown response when connecting to the FTP server: "
+ response);
}
sendLine("USER " + user, sendToLog);
response = waitForResponse(sendToLog);
if (!response.startsWith("331")) {
throw new IOException(
"FuriousFTP received an unknown response after sending the user: "
+ response);
}
sendLine("PASS " + pass, sendToLog);
response = waitForResponse(sendToLog);
if (!response.startsWith("230")) {
throw new IOException(
"FuriousFTP was unable to log in with the supplied password: "
+ response);
}
socket.setSoTimeout(0);
socket.setKeepAlive(true);
keepAliveTimer.start();
}
}
// Disconnects from the FTP server.
//**********************************************************************************
public synchronized void disconnect(boolean sendToLog) throws IOException {
try {
sendLine("QUIT", sendToLog);
waitForResponse(sendToLog);
}
finally {
keepAliveTimer.stop();
socket = null;
}
}
// Returns the working directory of the FTP server it is connected to.
//**********************************************************************************
public synchronized String pwd(boolean sendToLog) throws IOException {
sendLine("PWD", sendToLog);
String dir = null;
String response = waitForResponse(sendToLog);
if (response.startsWith("257")) {
int firstQuote = response.indexOf('\"');
int secondQuote = response.indexOf('\"', firstQuote + 1);
if (secondQuote > 0) {
dir = response.substring(firstQuote + 1, secondQuote);
}
}
return dir;
}
// Changes the working directory. Returns true if successful.
//**********************************************************************************
public synchronized boolean cwd(String dir, boolean sendToLog) throws IOException {
sendLine("CWD " + dir, sendToLog);
String response = waitForResponse(sendToLog);
return (response.startsWith("250"));
}
// Sends a file to be stored on the FTP server. Returns true if the file
// transfer was successful. The file is sent in passive mode to avoid NAT or
// firewall problems at the client end.
//**********************************************************************************
public synchronized boolean stor(File file, boolean sendToLog) throws IOException {
if (file.isDirectory()) {
throw new IOException("FuriousFTP cannot upload a directory.");
}
String filename = file.getName();
return stor(new FileInputStream(file), filename, sendToLog);
}
// Sends a file to be stored on the FTP server. Returns true if the file
// transfer was successful. The file is sent in passive mode to avoid NAT or
// firewall problems at the client end.
//**********************************************************************************
public synchronized boolean stor(InputStream inputStream, String filename, boolean sendToLog)
throws IOException {
BufferedInputStream input = new BufferedInputStream(inputStream);
Socket dataSocket = goPassive(sendToLog);
sendLine("STOR " + filename, sendToLog);
String response = waitForResponse(sendToLog);
if (!response.startsWith ("125") && !response.startsWith("150 ")) {
throw new IOException("FuriousFTP was not allowed to send the file: "
+ response);
}
BufferedOutputStream output = new BufferedOutputStream(dataSocket
.getOutputStream());
byte[] buffer = new byte[4096];
int bytesRead = 0;
while ((bytesRead = input.read(buffer)) != -1) {
output.write(buffer, 0, bytesRead);
}
output.flush();
output.close();
input.close();
response = waitForResponse(sendToLog);
return response.startsWith("226");
}
// Enter binary mode for sending binary files.
//**********************************************************************************
public synchronized boolean bin(boolean sendToLog) throws IOException {
sendLine("TYPE I", sendToLog);
String response = waitForResponse(sendToLog);
return (response.startsWith("200"));
}
// Enter ASCII mode for sending text files. This is usually the default mode.
// Make sure you use binary mode if you are sending images or other binary
// data, as ASCII mode is likely to corrupt them.
//**********************************************************************************
public synchronized boolean ascii(boolean sendToLog) throws IOException {
sendLine("TYPE A", sendToLog);
String response = waitForResponse(sendToLog);
return (response.startsWith("200"));
}
// Sends a raw command to the FTP server.
//**********************************************************************************
private synchronized void sendLine(String line, boolean sendToLog)
throws IOException
{
if (socket == null)
{
addToLog("FuriousFTP is not connected.");
}
else {
try {
writer.write(line + "\r\n");
writer.flush();
if(sendToLog) addToLog("> " + line);
} catch (IOException e)
{
System.out.println("problem while sending command");
e.printStackTrace();
}
}
}
// Reads a line from the Buffered Reader
//*************************************************************
private synchronized String readLine(boolean sendToLog)
throws IOException
{
String line = reader.readLine();
//String line = waitForResponse(sendToLog);
if(sendToLog) addToLog("< " + line);
return line;
}
// the method that the console calls to send a raw ftp command
//****************************************************************
public synchronized void sendCommand(String command,
boolean sendToLog)
{
if (socket == null) {
if(sendToLog) addToLog("FuriousFTP is not connected.");
}
else {
try
{
sendLine(command, sendToLog);
waitForResponse(sendToLog);
}
catch(IOException e)
{
System.out.println(e.getMessage());
e.printStackTrace();
}
}
}
public synchronized Socket goPassive(boolean sendToLog)
throws IOException
{
sendLine("PASV", sendToLog);
String response = waitForResponse(sendToLog);
if (!response.startsWith("227"))
{
System.out.println("error while attempting passive mode");
throw new IOException("FuriousFTP could not request passive mode: "
+ response);
}
String ip = null;
int port = -1;
int opening = response.indexOf('(');
int closing = response.indexOf(')', opening + 1);
if (closing > 0) {
String dataLink = response.substring(opening + 1, closing);
StringTokenizer tokenizer = new StringTokenizer(dataLink, ",");
try {
ip = tokenizer.nextToken() + "." + tokenizer.nextToken() + "."
+ tokenizer.nextToken() + "." + tokenizer.nextToken();
port = Integer.parseInt(tokenizer.nextToken()) * 256
+ Integer.parseInt(tokenizer.nextToken());
} catch (Exception e) {
System.out.println("bad data link information");
throw new IOException("FuriousFTP received bad data link information: "
+ response);
}
}
return new Socket(ip, port);
}
public synchronized String list(boolean sendToLog)
throws IOException
{
if (socket == null) {
if(sendToLog) addToLog("FuriousFTP is not connected.");
return null;
}
else {
ascii(sendToLog);
String outputString = "";
Socket dataSocket = goPassive(sendToLog);
BufferedInputStream input = new BufferedInputStream(dataSocket.getInputStream());
sendLine("LIST", sendToLog);
String response = waitForResponse(sendToLog);
if (!response.startsWith ("125") && !response.startsWith("150 ")) {
System.out.println("error while getting list");
throw new IOException("FuriousFTP was not allowed to retrieve the list: "
+ response);
}
ByteArrayOutputStream byteList = new ByteArrayOutputStream();
BufferedOutputStream output = new BufferedOutputStream(byteList);
byte[] buffer = new byte[4096];
int bytesRead = 0;
while ((bytesRead = input.read(buffer)) != -1) {
output.write(buffer, 0, bytesRead);
}
output.flush();
output.close();
input.close();
response = waitForResponse(sendToLog);
outputString = byteList.toString();
if(sendToLog) addToLog(outputString);
return outputString;
}
}
public synchronized String nlst(boolean sendToLog)
throws IOException
{
if (socket == null) {
if(sendToLog) addToLog("FuriousFTP is not connected.");
return null;
}
else
{
ascii(sendToLog);
String outputString = "";
Socket dataSocket = goPassive(sendToLog);
BufferedInputStream input = new BufferedInputStream(dataSocket.getInputStream());
sendLine("NLST", sendToLog);
String response = waitForResponse(sendToLog);
if (!response.startsWith ("125") && !response.startsWith("150 ")) {
System.out.println("error during nlst");
throw new IOException("FuriousFTP was not allowed to retrieve the list: "
+ response);
}
ByteArrayOutputStream byteList = new ByteArrayOutputStream();
BufferedOutputStream output = new BufferedOutputStream(byteList);
byte[] buffer = new byte[4096];
int bytesRead = 0;
while ((bytesRead = input.read(buffer)) != -1) {
output.write(buffer, 0, bytesRead);
}
output.flush();
output.close();
input.close();
response = waitForResponse(sendToLog);
outputString = byteList.toString();
if(sendToLog) addToLog(outputString);
return outputString;
}
}
public synchronized File retr(String fileName, boolean sendToLog)
throws IOException
{
if (socket == null) {
if(sendToLog) addToLog("FuriousFTP is not connected.");
return null;
}
else {
bin(sendToLog);
Socket dataSocket = goPassive(sendToLog);
BufferedInputStream input = new BufferedInputStream(dataSocket.getInputStream());
sendLine("RETR " + fileName, sendToLog);
String response = waitForResponse(sendToLog);
if (!response.startsWith("150")) {
System.out.println("error during retr");
throw new IOException("FuriousFTP was not allowed to retrieve the file: "
+ response);
}
ByteArrayOutputStream byteList = new ByteArrayOutputStream();
BufferedOutputStream output = new BufferedOutputStream(byteList);
byte[] buffer = new byte[4096];
int bytesRead = 0;
while ((bytesRead = input.read(buffer)) != -1) {
output.write(buffer, 0, bytesRead);
}
output.flush();
output.close();
input.close();
response = waitForResponse(sendToLog);
if (!response.startsWith("226")) {
System.out.println("error after download");
throw new IOException("FuriousFTP was unable to retrieve the file: "
+ response);
}
File tempFile = new File("/FFTP/Temp/" + fileName);
FileOutputStream fos = new FileOutputStream(tempFile);
fos.write(byteList.toByteArray());
fos.flush();
fos.close();
return tempFile;
}
}
public void clearLog()
{
log = "";
}
// method to wait until the Buffered Reader is ready, then get
// return the first line read as the response string
private String waitForResponse(boolean sendToLog)
throws IOException
{
while(!reader.ready())
{
System.out.println("Waiting for response...");
// THIS IS WHERE IT GETS STUCK!!!
}
String response = readLine(sendToLog);
while(reader.ready())
{
String temp = reader.readLine();
if(sendToLog) addToLog(temp);
}
return response;
}
// returns the log
//************************************************************
public String getLog()
{
return log;
}
// adds one line to the log
//**************************************************************
private void addToLog(String line)
{
log += (line + "\n");
}
}
Message was edited by:
AsSiDuL0Us