Skip to Main Content

Java APIs

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Reading from a Socket Input Stream

843790Apr 14 2007 — edited Nov 18 2007
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
Comments
Locked Post
New comments cannot be posted to this locked post.
Post Details
Locked on Dec 16 2007
Added on Apr 14 2007
8 comments
1,173 views