2012-10-26 43 views
7

我的问题是我正在创建一个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 ([email protected]) 
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 

回答

7

如果你有消息仔细看,你会发现所有,但最后几行有身份的代码背后-。最后一行有,但是,表示最后一行。

可以读取,在RFC 959,第4.2节:

因此,对于多行的格式回答是,第一线 将与所需的确切答复代码开始,随后立即 一个连字符, “ - ”(又称减号),后跟 文字。最后一行将以相同的代码开头,紧跟在 之后的空格,可选的一些文本和Telnet 行尾代码。

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


更新:FTP协议似乎受到严重的记载,但我发现了另一个参考,说明我一样上面:

TCP/IP Guide提到

这是可能的答复包含多行文本。在这种情况下,每行都以答复代码开始,除了最后一行之外,所有行都在答复代码和答复文本之间有一个连字符,以指示答复继续。最后一行在回复代码和回复文本之间留有空格,就像单行回复一样。该设施通常用于在用户登录后通过230回复代码提供额外的回复信息。

+0

这是*多行*回复格式。来自同一部分:“一个FTP回复包含一个三位数字(以三个字母数字字符发送),后面跟着一些文本。”从规范中不清楚,但如果启动FileZilla,您将看到连接过程中唯一的ML响应是FEAT命令中的211响应。 – linski

+0

会相应更新:) – linski

0

你试过这样吗?

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

UPDATE:

由于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()); 
+0

不,我没有,但我很快就会尝试一下。 –

+1

但是,您不知道服务器是否真的完成了,或者是否有数据包正在运行,但尚未到达。更好地依靠协议提供的设施。 – glglgl

+0

@glglgl“我的问题是我正在创建一个FTP客户端......”看起来他正在实现协议的客户端。 – linski