You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Apache FTPClient连接Docker FTP服务器时遇连接关闭异常

问题描述

Scala FTP客户端代码

import org.apache.commons.net.ftp.FTPClient

import java.io.IOException

object FtpClient {

  def main(args: Array[String]): Unit = {

    val ftpClient = new FTPClient()

    try {
      ftpClient.connect("localhost", 21)
      val success = ftpClient.login("one", "1234")

      if (success) {
        println("Success connect")
      }

    } catch {
      case e: IOException => throw new RuntimeException(e)
    } finally {
      // 
    }

  }
}

Docker启动FTP服务器命令

docker run -d     -p 21:21     -p 21000-21010:21000-21010     -e USERS="one|1234"     -e ADDRESS=ftp.site.domain     delfer/alpine-ftp-server

客户端错误信息

Exception in thread "main" java.lang.RuntimeException: org.apache.commons.net.ftp.FTPConnectionClosedException: Connection closed without indication.
at ru.spb.client.FtpClient$.main(FtpClient.scala:23)
at ru.spb.client.FtpClient.main(FtpClient.scala)
Caused by: org.apache.commons.net.ftp.FTPConnectionClosedException: Connection closed without indication.
at org.apache.commons.net.ftp.FTP.getReply(FTP.java:568)
at org.apache.commons.net.ftp.FTP.getReply(FTP.java:556)

Docker日志信息

Changing password for one
New password:
Bad password: too short
Retype password:
adduser: /ftp/one: No such file or directory
passwd: password for one changed by root
seems like pidfd_open syscall does not work, falling back to
polling
failed to watch for direct child exit (pidfd_open error): Operation not permitted

提问:是否遗漏了某些重要的连接设置?


问题分析与解决

从Docker日志和客户端错误来看,核心问题出在FTP服务器配置和客户端连接设置两方面:

1. 修复FTP服务器配置

日志里的两个关键错误直接导致用户无法正常登录:

  • Bad password: too short:该镜像默认要求密码至少6位,你设置的1234不符合规则
  • adduser: /ftp/one: No such file or directory:用户目录创建失败,服务器会直接断开连接

修改Docker启动命令,使用符合要求的密码并调整地址适配本地测试:

docker run -d \
  -p 21:21 \
  -p 21000-21010:21000-21010 \
  -e USERS="one|123456" \
  -e ADDRESS=localhost \
  delfer/alpine-ftp-server

2. 完善客户端连接设置

原客户端代码缺少FTP连接的关键配置,补充以下内容:

  • 开启被动模式(Docker环境下被动模式更易穿透端口映射)
  • 检查服务器连接响应
  • 添加连接关闭的收尾逻辑

修改后的代码:

import org.apache.commons.net.ftp.FTPClient
import java.io.IOException

object FtpClient {
  def main(args: Array[String]): Unit = {
    val ftpClient = new FTPClient()
    try {
      ftpClient.connect("localhost", 21)
      // 检查服务器连接响应
      val replyCode = ftpClient.getReplyCode()
      if (!ftpClient.isPositiveCompletion(replyCode)) {
        throw new IOException("FTP server refused connection")
      }
      // 启用被动模式
      ftpClient.enterLocalPassiveMode()
      val success = ftpClient.login("one", "123456")
      if (success) {
        println("Success connect")
        // 示例:列出服务器目录文件
        val files = ftpClient.listFiles()
        files.foreach(f => println(s"File: ${f.getName}"))
      } else {
        println("Login failed")
      }
    } catch {
      case e: IOException => throw new RuntimeException(e)
    } finally {
      // 关闭连接的收尾操作
      if (ftpClient.isConnected) {
        try {
          ftpClient.logout()
          ftpClient.disconnect()
        } catch {
          case e: IOException => e.printStackTrace()
        }
      }
    }
  }
}

3. 验证修复效果

重新启动FTP服务器,运行修改后的客户端代码,即可正常连接并登录。

内容的提问来源于stack exchange,提问作者Jelly

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 01:13:11