Java - 套接字 - 显示服务器上所有文件的名称

标签 java sockets ftp rfc

我正在尝试制作仅使用套接字的 ftpclient。我正在与服务器建立连接,但我不知道如何显示文件。这是我的代码:

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;
    }
}

我尝试使用 LIST、NLST、MLSD 但仍然不起作用。在控制台中我有:

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

还有“Client:LIST”我必须等待很长时间。之后我得到:

SERVER: 421 Connection timed out.

有人可能知道我做错了什么吗?

<小时/>

我现在编辑了这个方法:

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);
    }

现在我的结果是:

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 "/"

但它仍然不显示任何文件。

<小时/>

现在,当“bool firstSocket”为 false 时,我编辑为从 reader2 读取。所以它应该在发送“LIST”命令后从“reader2”读取,但它仍然不显示任何内容。

(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();

最佳答案

只有在收到对 LIST 命令的 1xx 响应后,您才能尝试连接到 PASV 响应中返回的 IP/端口。

您必须将LIST命令发送到(主)控制连接,而不是数据连接。

阅读RFC 959了解详情。

关于Java - 套接字 - 显示服务器上所有文件的名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41383163/

相关文章:

java - 打印类中的所有变量值

java - 在 Java 中使用 DecimalFormat 进行舍入

c - in_addr_t 变量作为连接参数

c# - 套接字术语 - "blocking"是什么意思?

java - 使用 Observable.timeout 超时后会发生什么?

java - 描述类型问题

Java SSLSocket - 如何设置本地端口

c# - 在 C# 中从 FTP 服务器检索文件列表

php - ftp_get 适用于本地主机,但不适用于生产服务器

python - 使用 Numpy 在 Python 中处理图像