【问题标题】:How to know the end of FTP Welcome message如何知道 FTP 欢迎信息的结束
【发布时间】:2012-10-16 11:02:32
【问题描述】:

我的问题是我正在创建一个 FTP 客户端,到目前为止,除了一个小细节之外,它的工作完美无缺,这一直困扰着我。 我需要知道 FTP 欢迎消息跨越了多少行...这是不能接受的!

    private Socket connection;
    private PrintWriter outStream;
    private Scanner inStream;

public void InitiateConnection() throws IOException 
{
    log.Info(this, "Initiating connection to host: " + host + ":" + port);
    connection = new Socket(host, port);
    log.Info(this, "Connection initiated.");
    outStream = new PrintWriter(connection.getOutputStream(), true);
    inStream = new Scanner(connection.getInputStream());
    Listen();
    Listen();    
    Listen();
}

public String Listen() throws IOException
{
    if(connection == null)
        throw new IOException("Connection not initiated yet");
    String response = inStream.nextLine();
    log.Info(this, "Response: " + response);
    return response;
}

这是简单的设置,我省略了所有其他代码,因为它与我的问题没有任何关系。

我尝试了多种方法来实现这一目标。 失败的解决方案 1:

String response = "";
while(response != null)
    Listen();

失败的解决方案 2:

while(connection.getInputStream().available > 0)
    Listen();

还有无数其他的......但要么它不起作用,要么方法阻塞并等待新的输入。我什至尝试过超时,但这也不能完美地工作,它不是解决这个问题的正确方法......

我需要能够从 FTP 服务器获取整个欢迎消息,而无需知道行数... 所以我都可以得到这个:

Response:   220-FileZilla Server version 0.9.39 beta
Response:   220-written by Tim Kosse (Tim.Kosse@gmx.de)
Response:   220 Please visit http://sourceforge.net/projects/filezilla/

还有这个:

Response:   220-FileZilla Server version 0.9.40 beta
Response:   220 Welcome to Andrés FTP Server

【问题讨论】:

    标签: java sockets ftp inputstream


    【解决方案1】:

    如果您仔细查看这些消息,您会发现除了最后几行之外的所有消息的状态码后面都有一个-。最后一行有一个,但是,表示最后一行。

    您可以在RFC 959,第 4.2 节中阅读:

    因此,多行回复的格式是第一行 将从所需的确切回复代码开始,然后是 紧接着是连字符“-”(也称为减号),然后是 文本。最后一行将以相同的代码开头,然后是 立即由 Space ,可选的一些文本和 Telnet 行尾代码。

    第二行到倒数第二行没有任何说明,但它们与第一行的格式相同是合乎逻辑的。


    更新:FTP 协议的文档似乎很糟糕,但我发现另一个参考说明与上面的我相同:

    TCP/IP Guide 提到了这一点

    回复可能包含多行文本。在这种情况下,每一行都以回复代码开头,除最后一行之外的所有行在回复代码和回复文本之间都有一个连字符,表示回复继续。最后一行在回复代码和回复文本之间有一个空格,就像单行回复一样。此工具通常用于在用户登录后通过 230 回复代码提供额外的响应信息。

    【讨论】:

    • 这是 multiline 回复格式。来自同一部分:“FTP 回复由一个三位数字(以三个字母数字字符传输)和一些文本组成。”从规范中并不清楚,但如果你启动 FileZilla,你会看到连接过程中唯一的 ML 响应是 FEAT 命令的 211 响应。
    • 虽然 TCP/IP 指南的示例符合 RFC 959,但它对要求的描述是不正确的。 RFC 959 第 4.2 节包含一个多行回复的示例。只有第一行必须以 3 位数字开头,后跟连字符。之后,唯一的要求是最后一行(并且只有最后一行)必须以与第 1 行相同的 3 位数字开头,后跟一个空格。
    【解决方案2】:

    你试过这样吗?

        StringBuilder response = new StringBuilder();
        BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
        do {            
            response.append(br.readLine());                                     
        }
        while (br.ready());
    

    BufferedReaderready() 方法:

    判断此流是否已准备好被读取。如果缓冲区不为空,或者底层字符流已准备好,则缓冲字符流已准备就绪。
    退货:
    如果保证下一个 read() 不会阻塞输入,则为 true,否则为 false。请注意,返回 false 并不能保证下一次读取会阻塞。

    其实是Readermethod

    更新:

    正如 glglgl 指出的,FTP 中有两种类型的响应:

    • “单行”响应(我的术语)
    • 多行响应(规范术语)

    正如我在评论中所说,启动 FIlleZilla,连接并观察日志(最好将输出中的命令与规范定义进行比较),你就会明白为什么引用了“单行”。

    在某些 FTP 服务器实现上,上述代码可能有效,但它可能无法在所有实现上有效,因为它没有正确实现协议的客户端部分。这是更新版本:

    String response;
    List<String> responseList = new ArrayList<String>();  
    boolean isMultilineStart = false, isMultilineEnd = false;
    String mlCode = null;
    do {            
       responseList.add(br.readLine());                           
       if (!isMultilineStart) {
            isMultilineStart = responseList.get(responseList.size()-1).matches("\\d\\d\\d-.*");                
            mlCode = responseList.get(responseList.size()-1).substring(0,3);
       }
       else {
           isMultilineEnd = responseList.get(responseList.size()-1).startsWith(mlCode+" ");
       }
    }
    while (br.ready() || (isMultilineStart && !isMultilineEnd));   
    response = Arrays.deepToString(responseList.toArray());
    

    【讨论】:

    • 不,我没有,但我肯定会尝试一下。
    • 但是你不知道服务器是否真的完成了,或者一个数据包在途中,但还没有到达。更好地依赖协议提供的设施。
    • @glglgl “我的问题是我正在创建一个 FTP 客户端......”看起来他正在实现协议的客户端。
    • 当然。但是客户端必须知道服务器何时完成,而 FTP 协议准确定义了这种情况。
    • @glglgl 同意。 available() 和 ready() 的正确用法很少,这不是其中之一。 -1.
    猜你喜欢
    • 2021-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-19
    • 2023-03-26
    相关资源
    最近更新 更多