2012-10-26 81 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