簡體   English   中英

在 Android 模擬器中從本地 FTP 服務器下載時出現錯誤“227 進入被動模式”/“連接被拒絕”

[英]Error "227 Entering Passive Mode"/"Connection refused" when downloading from local FTP server in Android emulator

我正在嘗試使用在 Android 模擬器中運行的 Java FTPSClient從本地 FileZilla 服務器下載文件。

我寫了這個幫助代碼來下載一個文件:

public boolean downloadSingleFile(FTPSClient ftpClient,
                                  String remoteFilePath, File downloadFile) {
    OutputStream outputStream;
    Log.i("t1", remoteFilePath + " - " + downloadFile.getAbsolutePath());
    try {
        outputStream = new BufferedOutputStream(new FileOutputStream(
                downloadFile));
        ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
        boolean retval = ftpClient.retrieveFile(remoteFilePath, outputStream);
        outputStream.flush();
        return retval;
    } catch (Exception e) {
        Log.e("dwFile", e.toString());
        Log.e("dwFile", ftpClient.getReplyString());
    } return false;
}

我這樣稱呼這個函數:

FTPSClient dwClient = new FTPSClient();
dwClient.addProtocolCommandListener(
    new PrintCommandListener(
    new PrintWriter(new OutputStreamWriter(System.out, "UTF-8")), true));
dwClient.setConnectTimeout(30 * 1000);
dwClient.connect(OmsSettingsFunctions.getFTPServer());
Log.i("dwDB", dwClient.getReplyString());
if (dwClient.login(FPTuser, FTPpass))  {
    Log.i("dwDB", dwClient.getReplyString());
    dwClient.enterLocalPassiveMode();
    File dwFile = new File(externalPath + "/Android/data/com.myapp/files/Documents/db.temp");
    if(!downloadSingleFile(dwClient, "/DBs/db.txt", dwFile)) {
        Log.e("dwDB", "Download could not finish (DB)");
        Log.e("dwDB", dwClient.getReplyString());
    }...

但我不斷收到此錯誤:

I/System.out: 220-FileZilla Server version 0.9.41 beta
I/System.out: 220-written by Tim Kosse (Tim.Kosse@gmx.de)
              220 Please visit http://sourceforge.net/projects/filezilla/
I/System.out: AUTH TLS
D/EGL_emulation: eglMakeCurrent: 0xa209dd60: ver 3 0 (tinfo 0x9f652ff0)
D/EGL_emulation: eglMakeCurrent: 0xa209dd60: ver 3 0 (tinfo 0x9f652ff0)
I/System.out: 234 Using authentication type TLS
I/dwDB: 234 Using authentication type TLS
I/Permission: Readingpermission is granted
I/Permission: Writingpermission is granted
I/System.out: USER *******
I/System.out: 331 Password required for omstest
I/System.out: PASS *******
I/System.out: 230 Logged on
I/dwDB: 230 Logged on
I/t1: /DBs/db.txt - /storage/0FF0-280B/Android/data/com.myapp/files/Documents/db.temp
I/System.out: TYPE I
I/System.out: 200 Type set to I
I/System.out: PASV
I/System.out: 227 Entering Passive Mode (127,0,0,1,199,113)
E/dwFile: java.net.ConnectException: Connection refused
          227 Entering Passive Mode (127,0,0,1,199,113)
E/dwDB: Download could not finish (DB)
        227 Entering Passive Mode (127,0,0,1,199,113)

我已經嘗試使用enterLocalActivemode()而不是enterLocalPassivmode()但它沒有幫助。 FTP 服務器在我的本地機器上執行和運行 TLS。 我通過 10.0.2.2(Android 環回)連接到它。 我怎樣才能解決這個問題?

雖然我不熟悉 Android Emulator,但我假設您需要連接到 10.0.2.2 才能連接到模擬器主機。

在 FTP 被動模式下,服務器發回一個 IP 地址,FTP 客戶端需要連接到該地址來傳輸文件(或目錄列表)。 當您的 FTP 服務器偵聽 127.0.0.1 時,它會發回該 IP 地址。 但是 127.0.0.1 指的是(模擬的)Android 主機,在您的 Android 代碼上下文中。 因此,“連接被拒絕”。

這與連接到 NAT 后面的 FTP 服務器的常見問題非常相似。 請參閱通過 NAT 在端口 2000 上運行的 FTP 服務器無法在被動模式下工作

因此解決方案是相同的:

  • 在 FileZilla 服務器界面中,轉到編輯 > 設置 > 被動模式設置 > IPv4 特定 > 被動模式傳輸的外部服務器 IP 地址 並輸入 10.0.2.2。
  • 也許您還需要取消選中“不要將外部 IP 用於本地連接”

顯然,這反過來又使普通客戶端無法使用 FTP 服務器。

並且您已正確評論,此問題僅在從 Android 模擬器連接到在模擬器主機上運行的 FTP 服務器時出現。


另一種解決方案是使用FTPClient.setPassiveNatWorkaroundStrategy 它接受HostnameResolver接口的實現。 如果您以將 127.0.0.1 轉換為 10.0.2.2 的方式實現,即使服務器上沒有任何更改,它也將允許您的 Java 代碼連接。

public static class ServerResolverImpl implements HostnameResolver {
    private FTPClient client;

    public ServerResolverImpl(FTPClient client) {
        this.client = client;
    }

    @Override
    public String resolve(String hostname) throws UnknownHostException {
        return this.client.getRemoteAddress().getHostAddress();
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM