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

时间:2012-10-26 07:21:01

标签: java sockets ftp inputstream

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

2 个答案:

答案 0 :(得分:8)

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

您可以在RFC 959第4.2节

中阅读
  

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

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


更新:FTP协议似乎记录不完整,但我发现另一条引用与上面的描述相同:

TCP/IP Guide提及

  

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

答案 1 :(得分: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

更新:

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

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

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

在某些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());