如何知道FTP欢迎消息的结束

我的问题是我正在创建一个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 

如果仔细查看消息,您会看到除了最后一行之外的所有行都有-在状态代码后面。 最后一行有一个 然而,表明最后一行。

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

因此,多行回复的格式是第一行将以确切的所需回复代码开头,紧接着是连字符,“ – ”(也称为Minus),后跟文本。 最后一行将以相同的代码开头,紧接着是Space,可选的是一些文本,以及Telnet的行尾代码。

关于第二到第二行没有任何说法,但它们具有与第一行相同的格式是合乎逻辑的。


更新:FTP协议似乎记录严重,但我发现另一个参考说明与我相同:

TCP / IP指南提到了这一点

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

你试过这样的吗?

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

而BufferedReader的ready()方法:

判断此流是否可以读取。 如果缓冲区不为空,或者基础字符流已准备就绪,则缓冲字符流就绪。
返回:
如果保证下一个read()不阻止输入,则返回true,否则返回false。 请注意,返回false并不能保证下一次读取将被阻止。

它实际上是一种读者的方法 。

更新:

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

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

正如我在评论中所说,启动FIlleZilla,连接并观察日志(最好将输出中的命令与spec defintion进行比较),您将看到为什么引用“单行”。

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

 String response; List responseList = new ArrayList(); 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()); 
Interesting Posts