8

私の問題は、私が FTP クライアントを作成していることです。これまでのところ、1 つの細かい点を除けば問題なく動作しており、それが私を悩ませ続けています。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
4

2 に答える 2

8

メッセージをよく見ると、最後の行を除くすべての行の-後ろにステータス コードがあることがわかります。ただし、最後の行には、最後の行を示す があります。

RFC 959のセクション 4.2でそれを読むことができます。

したがって、複数行の返信の形式は、最初の行が正確に必要な返信コードで始まり、すぐにハイフン「-」(マイナスとも呼ばれる) が続き、その後にテキストが続きます。最後の行は同じコードで始まり、すぐに Space 、オプションでテキスト、および Telnet の行末コードが続きます。

2 行目から最後 2 行目については何も述べられていませんが、1 行目と同じ形式であることは論理的です。


更新: FTP プロトコルは文書化されていないようですが、上記と同じことを述べている別の参考文献を見つけました。

TCP/IP ガイドには、次のように記載されています。

返信に複数行のテキストを含めることができます。この場合、各行は応答コードで始まり、最後の行を除くすべての行で、応答コードと応答テキストの間にハイフンがあり、応答が続くことを示します。最後の行には、1 行の返信と同様に、返信コードと返信テキストの間にスペースがあります。この機能は、ユーザーがログインした後に、230 応答コードを介して追加の応答情報を提供するためによく使用されます。

于 2012-10-26T08:05:58.603 に答える
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 を返すことは、次の読み取りがブロックされることを保証しないことに注意してください。

これは実際には読者方法です。

アップデート:

glglgl が指摘したように、FTP には 2 種類の応答があります。

  • 「一行」応答(私の用語)
  • 複数行の応答 (仕様用語)

コメントで述べたように、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());
于 2012-10-26T07:37:52.387 に答える