0

我正在使用带有 JAVA 的 FTP 传输文件。我正在使用来自 Apache 的FTPClientFTPServer 。但在特定环境中,有时文件不会传输。我在登录方法调用之前从FTPClient调用enterLocalPassiveMode方法,但有时文件没有传输。

  1. storeFile方法返回“false”。
  2. getReplyString方法返回“ 200 Command TYPE OK”。
  3. list 方法返回“227”。

当文件传输成功时:

  1. list方法返回 150 。
  2. getReplyString方法返回“ 150 文件状态正常;即将打开数据连接”。

客户端代码:

        this.getFtpClientUtil().connect(settingsService.getServer(), settingsService.getFtpServerCommandChannelPort());

        int reply = this.getFtpClientUtil().getReplyCode();

        if (!FTPReply.isPositiveCompletion(reply)) {
            logger.error("Fail to connect to FTP Server");
            this.getFtpClientUtil().disconnect();
            isConnect = false;
            return false;
        }

        logger.info("FTP Server connected successfully");
        this.getFtpClientUtil().enterLocalPassiveMode();
        isConnect = this.getFtpClientUtil().login(settingsService.getftpUsername(), settingsService.getftpPassword());

服务器代码:

        // Data Configuration
        this.dataConfigurationFactory = new DataConnectionConfigurationFactory();
        dataConfigurationFactory.setPassiveAddress(this.ipAddress);
        dataConfigurationFactory.setPassiveExternalAddress(this.ipAddress);
        dataConfigurationFactory.setPassivePorts(this.settingsService.getFtpServerTransferChannelPort());

        // Listener
        listenerFactory = new ListenerFactory();
        listenerFactory.setPort(this.settingsService.getFtpServerCommandChannelPort());
        listenerFactory.setDataConnectionConfiguration(dataConfigurationFactory.createDataConnectionConfiguration());

        // Desliga SSL
        listenerFactory.setImplicitSsl(false);

        // User
        PropertiesUserManagerFactory userManagerFactory = new PropertiesUserManagerFactory();
        UserManager um = userManagerFactory.createUserManager();

        this.serverFactory = new FtpServerFactory();
        serverFactory.addListener("default", listenerFactory.createListener());
        serverFactory.setUserManager(um);

        UserFactory userFactory = new UserFactory();
        userFactory.setName(this.settingsService.getftpUsername());
        userFactory.setPassword(this.settingsService.getftpPassword());
        userFactory.setMaxIdleTime(60);

        final String absolutePath = this.settingsService.getftpHomeDirectory();

        userFactory.setHomeDirectory(absolutePath);
        userFactory.setAuthorities(Arrays.asList((Authority) new WritePermission()));

        User user = userFactory.createUser();
        um.save(user);

        // Connection Config
        connectionConfigFactory = new ConnectionConfigFactory();
        connectionConfigFactory.setAnonymousLoginEnabled(false);
        connectionConfigFactory.setMaxLogins(100);
        serverFactory.setConnectionConfig(connectionConfigFactory.createConnectionConfig());

这是防火墙问题吗?

我尝试使用DataConnectionConfigurationFactory类中的setPassivePorts方法在服务器端设置被动端口范围,但问题仍然存在。

是否有任何形式可以在客户端设置端口范围?如何检查连接是否真的使用被动模式?

提前致谢。

4

1 回答 1

0

这是防火墙问题吗?

在这些情况下,正确的方法是关闭防火墙以测试或设置应用程序可以连接的端口范围。但在生产环境中,这不是一个选择。所以,我唯一知道的是,在开发环境中工作正常,在生产环境中出现问题。我的假设是防火墙阻止了端口。

是否有任何形式可以在客户端设置端口范围?如何检查连接是否真的使用被动模式?

本地端口可以在 FTPClient 的 connect() 方法中设置:

this.getFtpClientUtil().connect(settingsService.getServer(), settingsService.getFtpServerCommandChannelPort(), 
                InetAddress.getLocalHost(), getLocalPort());

可以通过两种方式验证连接是否使用被动模式:

  1. 如果未使用被动模式,来自 FTPClient 的 getPassivePort() 方法将返回 -1。
  2. 在问题中,我提到 FTPClient 的 list() 方法返回 227 代码。此代码还表示正在使用被动模式。我认为这段代码是一个错误。真正发生的是进入被动模式后出现错误,但返回了上一个命令的代码。

设置本地端口并没有解决问题。也许是因为我正在配置的本地端口仅用于命令通道。传输通道仍然使用客户端的随机端口。解决方案是尝试再次传输文件。如果传输失败,我断开客户端,然后使用其他端口再次连接客户端,然后尝试再次传输文件。在我所有的测试中,文件都在第二次成功传输。如果传输失败,我会尝试 3 次。

再次连接客户端时,如果使用相同的端口,java 可能会抛出“java.net.BindException: Address already in use”。即使在断开客户端连接后,端口仍会继续锁定片刻。在这种情况下,我会在尝试连接之前验证端口是否可用,如有必要,我会尝试将客户端连接到另一个端口。

于 2016-07-27T14:25:48.587 回答