3

これは、私が特定のコンピューターを使用しているときにのみ発生するように見える、少しあいまいな問題です。今日、私は学校のXPコンピューターでこの問題を抱えていましたが、自宅のコンピューター(W7)ではこれを再現できないようです。

とにかく、Javaでのソケットの読み取り/書き込みは、このコードを使用するたびに問題になる傾向があります(ここで:) int avail, InputStream socket, byte[] buffer, String output

                   while( (avail = input.available()) > 0 )
                    {
                        read = input.read( buffer );
                        output += new String( buffer, 0, read );
                    }

理にかなっているようですが(一時バッファーで使用できるデータがなくなるまですべてのデータを読み取り、次に文字列で読み取る)、学校のコンピューター(IE7を使用してテスト)では、すべてが一時停止します。input.available()が原因で、スレッドがエンドポイントに到達することなく実行を継続しているため、何らかの理由でブロックされていると思います...事実上、どこかで一時停止しているだけです。

ああ、私は言及するのを忘れました:これをデバッグモードで実行し、各行を段階的に実行するときはいつでも、それは完全に正常に機能します...それは私をさらに混乱させます。

この問題を再現するために家に帰ったとき、それは問題なく動作します(FirefoxとIE8を使用するだけです)。私はこれに代わるより良い方法が何であるかわかりません。

PS:バッファが十分に大きく、私が使用する場合:

                    read = input.read( buffer );
                    output += new String( buffer, 0, read );

正常に動作しますが、送信されるデータがバッファサイズを超えるという懸念が常にあります。

4

3 に答える 3

3

あなたはavailable()間違った方法について考えています。このメソッドは、ブロックせずに、現在読み取ることができるおおよそのバイト数を示します。あなたがやろうとしていることについて一般的に受け入れられているイディオムは

int length;
while ((length = in.read(buffer)) != -1) {
    output += new String(buffer, 0, length);
}

またはそれらの線に沿った何か(コンパイル/テストされていません)。

更新:「ストリームの終わり」の概念を誤解していると思います。「ストリームの終わり」は、読み取りたいすべてのデータが読み取られたことを意味するわけではありません。これは、他に読むものがないこと、そしてこれからも存在しないことを意味します。たとえば、ファイルを読み取っていてそのファイルの最後に到達したことを意味する場合もあれば、メモリ内のバイト配列から読み取ってそのファイルの最後に到達したことを意味する場合もあります。それらは「ストリームの終わり」です。

あなたの質問では、あなたはソケットから読んでいることを示したか、少なくとも暗示しています。関連するソケットまたは接続のリモートエンドが閉じられるまで、そのストリームの終わりに到達しないことを知っていますか?そこから少しのデータを受け取ったからといって、それがストリームの終わりになるわけではありません。

于 2012-05-22T02:26:15.387 に答える
1

コードが無効です。これはの誤用ですavailable()。それが行うのは、ブロックせずに読み取ることができるバイト数を通知することだけです。ピアによって送信されるバイト数を示すために使用することはできず、ピアメッセージとの必要な関係はありません。TCPにはメッセージはなく、バイトストリームのみです。EOSに読みたい場合は、available()テストを削除して、-1が返されるまで読みます。メッセージを読みたい場合、ピアは、たとえば、帯域外ターミネータ、長さの単語プレフィックス、またはオブジェクトのシリアル化やXMLなどの自己記述型プロトコルによって、メッセージを何らかの方法で区切る必要があります。

ブレークポイントでタイミングを根本的に変更しているため、デバッグモードで「機能」します。これは、あなたがしていることが正しくないことのさらなる証拠です。

于 2012-05-22T03:41:29.760 に答える
1

バッファ付きリーダーを使用してみませんか?何かのようなもの:

    BufferedReader reader = new BufferedReader(new InputStreamReader(input));
    String output = "";
    try {
        String readLine = null;
        while ((readLine = reader.readLine()) != null) {
            output += readLine + "\n";
        }
    } catch (IOException e) {
        System.err.println("Error: " + e);
    }
    System.out.println("Read from Socket:" + output);
于 2012-05-22T02:31:57.517 に答える