8

クラス InputStream の JavaDoc には、次のように記載されています。

入力ストリームから最大 len バイトのデータをバイト配列に読み取ります。len バイトまで読み取ろうとしますが、それより少ない数が読み取られる可能性があります。実際に読み取られたバイト数は整数として返されます。このメソッドは、入力データが使用可能になるか、ファイルの終わりが検出されるか、例外がスローされるまでブロックされます。

これは私の経験とも一致します。たとえば、以下のコード例を参照してください。

Client:
Socket socket = new Socket("localhost", PORT);
OutputStream out = socket.getOutputStream();
byte[] b = { 0, 0 };
Thread.sleep(5000);
out.write(b);
Thread.sleep(5000);
out.write(b);

Server:
ServerSocket server = new ServerSocket(PORT);
Socket socket = server.accept();
InputStream in = socket.getInputStream();
byte[] buffer = new byte[4];
System.out.println(in.read(buffer));
System.out.println(in.read(buffer));

Output:
2   // Two bytes read five seconds after Client is started.
2   // Two bytes read ten seconds after Client is started.

入力データが使用可能になるまで、read(buffer) ブロックへの最初の呼び出し。ただし、バイト バッファーにまだ余裕があるにもかかわらず、メソッドは 2 バイトが読み取られた後に戻ります。ただし、入力ストリームがソケットから来るときに少なくとも 1 バイトのデータが読み取られると、メソッドがブロックされないことが保証されていますか?

私が尋ねる理由は、小さな Java Web サーバーNanoHTTPDで次のコードを見たからです。8k バイト (ほとんどの要求はそうです) より小さい HTTP 要求は、保証がない限り、スレッドを無期限にブロックする可能性があるかどうか疑問に思いました。一部のデータが読み取られると、ブロックされません。

InputStream is = mySocket.getInputStream();
// Read the first 8192 bytes. The full header should fit in here.
byte[] buf = new byte[8192];
int rlen = is.read(buf, 0, bufsize);

編集

比較的似たコード例でもう一度説明してみましょう。EJP は、メソッドが EOS が通知されるか、少なくとも 1 バイトのデータが到着するまでブロックすると言いますクラス InputStream の read(byte[], int, int)。ただし、実際にソース コードを見ると、バッファがいっぱいになるまでメソッドが実際にブロックされることは明らかです。上記と同じクライアントを使用し、サーバーの例で InputStream コードを静的メソッドにコピーしてテストしました。

public static void main(String[] args) throws Exception {
    ServerSocket server = new ServerSocket(PORT);
    Socket socket = server.accept();
    InputStream in = socket.getInputStream();
    byte[] buffer = new byte[4];
    System.out.println(read(in, buffer, 0, buffer.length));
}

public static int read(InputStream in, byte b[], int off, int len) throws IOException {
    if (b == null) {
        throw new NullPointerException();
    }
    else if (off < 0 || len < 0 || len > b.length - off) {
        throw new IndexOutOfBoundsException();
    }
    else if (len == 0) {
        return 0;
    }

    int c = in.read();
    if (c == -1) {
        return -1;
    }
    b[off] = (byte)c;

    int i = 1;
    try {
        for (; i < len; i++) {
            c = in.read();
            if (c == -1) {
                break;
            }
            b[off + i] = (byte)c;
        }
    }
    catch (IOException ee) {
    }
    return i;
}

このコードの出力は次のとおりです。

4   // Four bytes read ten seconds after Client is started.

明らかに 5 秒後に利用可能なデータがありますが、メソッドはまだバッファ全体を埋めようとしてブロックしています。これは Socket.getInputStream() が返す入力ストリームには当てはまらないようですが、データが利用可能になると決してブロックされないことが保証されています.

4

1 に答える 1

5

ただし、入力ストリームがソケットから来るときに少なくとも 1 バイトのデータが読み取られると、メソッドがブロックされないことが保証されていますか?

この質問に意味はないと思います。このメソッドは、EOS が通知されるか、少なくとも 1 バイトのデータが到着するまでブロックします。この場合、再度ブロックすることなく、到着したデータのバイト数を読み取り、その数値を返します。

小さなJava WebサーバーNanoHTTPDで次のコードを見ました

コードが間違っています。ヘッダー全体が最初の読み取りで配信されるという無効な仮定を作成します。ここでは、空白行が検出されるまでループするループが見られると思います。

一部のデータが読み取られるとブロックされないという保証がない限り、8k バイト (ほとんどの要求はそうです) より小さい HTTP 要求がスレッドを無期限にブロックする可能性があるかどうか疑問に思いました。

繰り返しますが、これは何の意味もないと思います。このメソッドは、少なくとも 1 バイトまたは EOS が到着するまでブロックされます。限目。

于 2012-11-06T09:30:14.647 に答える