我的问题是我正在创建一个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
答案 0 :(得分:8)
如果仔细查看消息,您会发现除了最后一行之外的所有行都在状态代码后面有一个-
。最后一行有一个,但是,表明最后一行。
您可以在RFC 959第4.2节
中阅读因此,多行回复的格式是第一行 将以确切的所需回复代码开头,紧随其后 紧接着一个连字符,“ - ”(也称为Minus),然后是 文本。最后一行将以相同的代码开头,然后是 立即由Space,可选的一些文本和Telnet 行尾代码。
关于第二到第二行没有任何说法,但它们的格式与第一行格式相同是合乎逻辑的。
更新:FTP协议似乎记录不完整,但我发现另一条引用与上面的描述相同:
回复可能包含多行文本。在这种情况下,每行以回复代码开头,除了最后一行之外的所有行在回复代码和回复文本之间都有连字符,以指示回复继续。最后一行在回复代码和回复文本之间有一个空格,就像单行回复一样。此工具通常用于在用户登录后通过230回复代码提供其他响应信息。
答案 1 :(得分:0)
你试过这样的吗?
StringBuilder response = new StringBuilder();
BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
do {
response.append(br.readLine());
}
while (br.ready());
判断此流是否已准备好进行读取。如果缓冲区不为空,或者基础字符流已准备就绪,则缓冲字符流就绪。
返回:
如果保证下一个read()不阻止输入,则返回true,否则返回false。请注意,返回false并不能保证下一次读取将被阻止。
更新:
正如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());