7

Java から C++ アプリケーション (両方とも同じマシン上) に大量のデータ (最大 1 Gbit) をストリーミングしようとしています。現在 Linux で FIFO を使用していますが、Windows ソリューションも必要です。

最もクロスプラットフォームな方法はローカル ソケットのようですが、a) TCP チェックサムとカーネル空間との間のコピーから巨大なオーバーヘッドが発生しないでしょうか、b) 平均的なユーザーのファイアウォールは、および多分接続をブロックしますか?

JNI と名前付きパイプ API (\.\pipe\blah) を使用して、接続の両側でプラットフォーム固有の非常にひどい混乱を引き起こすことが、より安全な解決策のようです。

これらは本当に私の 2 つの最良のオプションですか (そして、どれをお勧めしますか?) ありがとう!

4

11 に答える 11

7

C++とJavaの両方をサポートするGoogleのProtocolBuffersを確認する必要があります。

于 2008-11-05T23:12:48.727 に答える
5

名前付きパイプは TCP よりも効率的ですが、共有メモリブロックを使用するだけではどうでしょうか?

Java 側に共有メモリとのインターフェイス用にどのようなプリミティブが存在するかはわかりませんが、C++ 側からは、ソケットまたは名前付きパイプからデータを読み取るよりも、共有メモリ内のデータにアクセスする方が効率的です。独自のフロー制御とブロッキング プリミティブを実装する必要がありますが、これらはかなり簡単です。

于 2008-11-05T22:16:26.173 に答える
4

あなたが述べているように、最もクロスプラットフォームな方法であるローカルソケットを使用します。

おそらく共有メモリを除いて、選択できる他の方法ではこの種のコピーが必要になるため、カーネルとユーザー空間のコピーは問題になりません。すべての Unix システムで利用でき、Windows にも独自の方法があります

Java で共有メモリを使用する唯一の方法は、独自の .DLL/.SO および JNI を使用して実装し、それにアクセスすることです。

于 2008-11-05T22:18:50.020 に答える
1

「1 つの」関数呼び出しで大量のデータを処理する場合は、JNI をお勧めします。

これを見てください: jni インターフェースを介して出力ストリームを共有する

記事のスニペット。C++ から Java にデータを転送します。逆も簡単です。

全体として、C からのバイナリ データ (A/V ファイル、画像など) を Java と共有するための一般的な戦略には、バイト配列が必要です。次のように C で Java バイト配列を作成します。

const char[] rawData = {0,1,2,3,4,5,6,7,8,9}; //Or get some raw data from somewhere
int dataSize = sizeof(rawData);
printf("Building raw data array copy\n");
jbyteArray rawDataCopy = env->NewByteArray(dataSize);
env->SetByteArrayRegion(rawDataCopy, 0, dataSize, rawData);

そして、次のように Java に渡します。

printf("Finding callback method\n");
//Assumes obj is the Java instance that will receive the raw data via callback
jmethodID aMethodId = env->GetMethodID(env->GetObjectClass(obj),"handleData","([B)V");
if(0==aMethodId) throw MyRuntimeException("Method not found error");
printf("Invoking the callback\n");
env->CallVoidMethod(obj,aMethodId, &rawDataCopy);

次のようなJavaオブジェクトがあります。

public class MyDataHandler {
  OutputStream dataStream;
  public MyDataHandler(OutputStream writeTo) { dataStream = writeTo;}
  public void handleData(byte[] incomingData) { dataStream.write(incomingData); }
}

そのハンドラは、次のようにネイティブ メソッドを介して C に渡されます。

public class NativeIntegration {
  public native void generateBinaryWithHandler(MyDataHandler handler);

  //Here we assume response is something like a network stream
  public void doCallNativeFunction(ResponseStream response) {
    MyDataHandler handler = new MyDataHandler(response);
    generateBinaryWithHandler(handler);
  }
}

また、CORBA、ASN.1 ( ASN.1 ツール)、UDP、または TCP などの他のテクノロジを使用することもできます。

于 2010-08-24T14:01:03.323 に答える
1

JNI の作成に満足している場合は、Boost.Interprocessを検討してください。これにより、Linux と Windows の両方で移植可能な共有メモリが提供されます。共有メモリを読み書きするためのカーネル ラウンドトリップがないことに注意してください。

于 2008-11-07T10:56:20.850 に答える
0

障害なく受信された N 番目のパケットごとに確認応答し、欠落するいくつかのパケットの再送信を要求する UDP "接続" をお勧めします。

于 2008-11-06T01:24:51.703 に答える
0

ビット レートが TCP に対して高すぎる場合は、否定応答 UDP でローカル ソケットを使用します (最初に TCP を試して、それが問題であることを確認します)。同じマシンでストリーミングを実行している場合、ドロップされるパケットは、あるとしても最小限に抑える必要がありますが、否定応答レイヤーを追加すると、そのケースが処理されます。

于 2008-11-05T22:59:52.357 に答える
0

System.out と System.in を使用するのはどうですか?

それが適切でない場合は、ソケットが最善の策です。

于 2008-11-05T23:04:48.570 に答える
0

C++ プロセスが Java プロセスを開始する場合、 inheritedChannelの恩恵を受ける可能性があります。また、Java プロセスがファイルを使用している場合は、transferToメソッドとtransferFromメソッドを調べることをお勧めします。ファイルからファイルへの IO を実行する場合、これらにより、ユーザー空間とカーネル空間の間を不必要に行き来することが回避されます。特別なソケット チャネルを使用している場合は、同じ最適化が開始される可能性があります。

于 2008-11-05T23:23:38.563 に答える
-2

デバッグが非常に難しいため、JNI は使用しないことをお勧めします。C++ コードがセグメンテーション違反を起こしたり、キャッチされない例外をスローしたりすると、JVM がクラッシュし、その理由がわかりません。

于 2008-11-05T22:30:22.260 に答える