Java - Sockets - display names of all files on server

968 views Asked by At

I'm trying to make ftpclient which will use only sockets. I'm making a connection with server but I don't have idea how to display files. Here is my code:

package pl.edu.ftp;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.*;

import pl.edu.config.ConfigData;

public class FTPProtocol {
    private Socket socket;
    private BufferedReader reader;
    private OutputStreamWriter writer;
    private Socket socket2;
    private BufferedReader reader2;
    private OutputStreamWriter writer2;
    private String serverImportantOutput;
    private boolean firstSocket = true;

    public void makeConnection(ConfigData configData) throws UnknownHostException, IOException, InterruptedException {
        socket = new Socket(configData.getServerAddress(), configData.getPort());
        reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        writer = new OutputStreamWriter(socket.getOutputStream());

        (new Thread(new Runnable() {
            public void run() {
                try {
                    String line;
                    if (firstSocket == true) {
                        while ((line = reader.readLine()) != null) {
                            System.out.println("SERVER: " + line);
                            if (line.startsWith("227 Entering Passive Mode")) {
                                serverImportantOutput = line;
                            }
                        }
                    } else {
                        while ((line = reader.readLine()) != null) {
                            System.out.println("SERVER: " + line);
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        })).start();

        Thread.sleep(2000);

        sendCommand("USER " + configData.getUsername());
        sendCommand("PASS " + configData.getPassword());
        sendCommand("SYST");
        sendCommand("FEAT");
        sendCommand("PWD");
        sendCommand("TYPE I");

        sendCommand("PWD");
        List<String> newData = sendCommandPasv("PASV");
        socket2 = new Socket(newData.get(0), Integer.parseInt(newData.get(1)));
        reader2 = new BufferedReader(new InputStreamReader(socket2.getInputStream()));
        writer2 = new OutputStreamWriter(socket2.getOutputStream());

        sendCommand2("LIST");
    }

    private void sendCommand(String command) throws IOException, InterruptedException {
        firstSocket = true;

        writer.write(command + "\r\n");
        writer.flush();
        System.out.println("Client:" + command);
        Thread.sleep(2000);
    }

    private void sendCommand2(String command) throws IOException, InterruptedException {
        firstSocket = true;
        writer2.write(command + "\r\n");
        writer2.flush();
        System.out.println("Client:" + command);
        Thread.sleep(2000);
        firstSocket = false;
        Thread.sleep(2000);
    }

    private List<String> sendCommandPasv(String command) throws IOException, InterruptedException {
        List<String> listOfStrings = new ArrayList<String>();

        writer.write(command + "\r\n");
        writer.flush();
        System.out.println("Client:" + command);
        Thread.sleep(2000);

        String fullAdress = serverImportantOutput.substring(serverImportantOutput.indexOf("(") + 1,
                serverImportantOutput.indexOf(")"));
        List<String> partsOfAdress = Arrays.asList(fullAdress.replaceAll("\\s+", "").split(","));

        String host = partsOfAdress.get(0) + "." + partsOfAdress.get(1) + "." + partsOfAdress.get(2) + "."
                + partsOfAdress.get(3);
        String port = Integer
                .toString(Integer.parseInt(partsOfAdress.get(4)) * 256 + Integer.parseInt(partsOfAdress.get(5)));

        System.out.println("Host: " + host);
        System.out.println("Port: " + port);

        listOfStrings.add(host);
        listOfStrings.add(port);

        return listOfStrings;
    }
}

I tried to use LIST, NLST, MLSD but still nothing work. In console I have:

SERVER: 227 Entering Passive Mode (127,0,0,1,197,183)
Host: 127.0.0.1
Port: 50615
Client:LIST

And "Client:LIST" I have to wait very long. After that I got:

SERVER: 421 Connection timed out.

Somebody have maybe any idea what I'm doing wrong?


I edited now this method:

private void sendCommand2(String command) throws IOException, InterruptedException {
        writer.write(command + "\r\n");
        writer.flush();
        System.out.println("Client:" + command);
        firstSocket = false;
        Thread.sleep(2000);
    }

And now as result I have:

SERVER: 227 Entering Passive Mode (127,0,0,1,196,72)
Host: 127.0.0.1
Port: 50248
Client:LIST
SERVER: 150 Opening data channel for directory listing of "/"
SERVER: 226 Successfully transferred "/"

But it still doesn't display any files.


Now I edited to read from reader2 when "bool firstSocket" is false. So it should read from "reader2" after sending "LIST" command, but it still display nothing.

(new Thread(new Runnable() {
            public void run() {
                try {
                    String line;
                    if (firstSocket == true) {
                        while ((line = reader.readLine()) != null) {
                            System.out.println("SERVER: " + line);
                            if (line.startsWith("227 Entering Passive Mode")) {
                                serverImportantOutput = line;
                            }
                        }
                    } else {
                        while ((line = reader2.readLine()) != null) {
                            System.out.println("SERVER: " + line);
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        })).start();
1

There are 1 answers

0
Martin Prikryl On BEST ANSWER

You can try to connect to the IP/port returned in the PASV response only after receiving 1xx response to the LIST command.

You have to send the LIST command to the (main) control connection, not to the data connection.

Read RFC 959 for details.