2

それは次のコードを確立しました、それはうまく機能しているようです:

void pipe(InputStream, OutputStream os) {
  try {
    try {
      byte[] buf = new byte[1024*16];
      int len, available = is.available();
      while ((len = is.read(buf, 0, available > 0 ? available : 1)) != -1) {
        os.write(buf, 0, len);
        available = is.available();
        if(available <= 0)
          os.flush();
      }
    } finally {
      try {
        os.flush();
      } finally {
        os.close();
      }
    }
  } finally {
    is.close();
  }
}

以前は、を呼び出すとis.read(buf)、データが利用可能であっても、バッファがいっぱいになるまでデータの待機がブロックされることがわかりました。これはTCPデータのエコーサーバーだったので、新しいデータが到着したらすぐにフラッシュする必要がありました。

私の最初の解決策は、一度に1つずつ非効率的でしたis.read()。後で、それが十分ではなかったとき、私は利用可能な方法を調べていて、見つけましis.available()た。APIは次のように述べています。

この数のバイトの単一の読み取りまたはスキップはブロックされません。

だから私は今かなり良い解決策を持っていますが、私にとって悪いと思われることの1つは、私がケースをどのように処理しているかですis.available() == 0。この場合、新しいデータが利用可能になるまで待つ方法として、1バイトを読み取るだけです。


データが到着するとすぐにフラッシュして、InputStreamからにデータを転送するための推奨される方法は何ですか?OutputStream上記のコードは本当に正しい方法ですか、それとも変更するか、新しいコードを使用する必要がありますか?おそらく、新しい非同期ルーチンのいくつかを使用する必要がありますか、それともこのための組み込みのJavaメソッドがありますか?

4

1 に答える 1

2

以前、is.read(buf)を呼び出すと、データが利用可能であっても、バッファーがいっぱいになるまでデータの待機がブロックされることがわかりました。

いいえ、しませんでした。TCPはそのようには機能しません。ソケットはそのようには機能しません。Javaソケットはそのようには機能しません。あなたは間違っています。

それはあなたが思っているよりもずっと簡単です:

while ((count = in.read(buffer)) > 0)
{
  out.write(buffer, 0, count);
}
out.close();
in.close();

ソケットの入力/出力ストリームにはバッファリングがないため、読み取られるとすぐに読み取られたすべてのものが書き込まれます。

この状況、または実際にはほとんどすべての状況でavailable()を呼び出すことは、完全に時間の無駄です。

これは、Javaであらゆる種類の入力ストリームをあらゆる種類の出力ストリームにコピーする方法でもあります。

非ブロッキングコードが必要な場合は、NIOを使用してください。しかし、私はあなたが本当にそうしているとは思いません。

于 2013-03-23T00:15:01.197 に答える