uso tuberias son que programacion por pipes los comunicacion bidireccionales java c++ pipe fifo

tuberias - Eficiente transferencia de datos de Java a C++ en Windows



tuberias bidireccionales en c (11)

Estoy buscando transmitir muchos datos (hasta ~ 1 Gbit) desde Java a una aplicación C ++ (ambos en la misma máquina). Actualmente estoy usando un FIFO en Linux pero también necesito una solución de Windows.

El método más multiplataforma parece ser un socket local, pero: a) ¿no obtendré una gran sobrecarga de la suma de comprobación y copia de TCP desde y hacia el espacio del kernel, yb) el firewall del usuario promedio no intentará inspeccionar el y tal vez bloquear la conexión?

Parece que una solución más segura puede ser utilizar JNI y la API Named Pipe (/. / Pipe / blah), creando un desastre espantoso específico para la plataforma en ambos lados de la conexión.

¿Estas son realmente mis 2 mejores opciones (y qué recomendaría la gente?) ¡Gracias!


¿Qué le parece usar System.out y System.in?

Si eso no es adecuado, entonces Sockets es tu mejor opción.


Aconsejaría contra JNI, porque es muy difícil de depurar. Si el código de C ++ segmenta o arroja una excepción no detectada, su JVM se bloqueará y no tendrá idea de por qué.



Las tuberías con nombre serían más eficientes que TCP, pero ¿qué tal si usamos bloques de memoria compartida ?

No sé qué primitivas existen en el lado de Java para interactuar con la memoria compartida, pero desde el lado de C ++ sería más eficiente acceder a los datos en la memoria compartida que leerlos desde un socket o canalización con nombre. Tendría que implementar sus propias primitivas de control de flujo y bloqueo, pero podrían ser bastante sencillas.


Si su proceso C ++ inicia el proceso Java, podría beneficiarse del inheritedChannel . Además, si el proceso de Java está usando un archivo, recomiendo la exploración de los métodos transferTo y transferFrom . Cuando se hace un archivo a un archivo IO, estos evitan innecesariamente ir y venir entre el usuario y el espacio del kernel; las mismas optimizaciones pueden activarse si está utilizando un canal de socket especial.


Usaría un socket local con UDP de reconocimiento negativo si la tasa de bits fuera demasiado alta para TCP (aunque probaría TCP primero y confirmaría que es un problema). Debe haber paquetes mínimos, si alguno, caídos si está haciendo la transmisión en la misma máquina, pero la adición de una capa de acuse de recibo negativa se encargará de ese caso por usted.


Usaría un socket local, que es, como dices, el método más multiplataforma.

Las copias del espacio Kernel-User no deberían ser un problema, ya que cualquier otro método que pudiera elegir requeriría este tipo de copia, excepto quizás la memoria compartida. Está disponible en todos los sistemas Unix y también Windows tiene su forma de hacerlo

Para utilizar la memoria compartida en Java, la única forma es implementarlo mediante su propio .DLL / .SO y JNI para acceder a él.


Recomiendo una "conexión" UDP que reconozca cada N paquete que se recibió sin errores, y solicita una retransmisión de los pocos paquetes que perderá.


Si está contento con escribir JNI, considere Boost.Interprocess . Esto le dará memoria compartida portátil tanto en Linux como en Windows. Recuerde que no hay una ida y vuelta del núcleo para leer / escribir memoria compartida.


La solución más rápida será la asignación de memoria a un segmento compartido de la memoria, y la implementación de un búfer de anillo u otro mecanismo de transmisión de mensajes. En C ++ esto es sencillo, y en Java tiene el método FileChannel.ma p que lo hace posible.

La siguiente alternativa sería usar stdin / stdout de los dos procesos. Si uno puede ejecutar al otro, esto puede ser bastante rápido.

Por último, como ha notado, puede hacer socket IO. Para la transmisión de video esta no es una gran opción, pero si pasas el XML, la sobrecarga será mínima en comparación con el otro procesamiento.


Si se trata de una gran parte de los datos en la llamada de "una" función, recomendaría JNI.

Eche un vistazo a esto: Compartir flujos de salida a través de una interfaz jni

Fragmento del artículo, transfiere datos de C ++ a Java, lo contrario también sería fácil de hacer:

En general, la estrategia general para compartir datos binarios (archivos A / V, imágenes, etc.) desde C con Java requiere matrices de bytes. Usted crea una matriz de bytes Java en C de esta manera:

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);

Y páselo a Java así:

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);

tendrías un objeto Java que se vería así:

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

Ese controlador se pasará a C a través del método nativo de la siguiente manera:

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); } }

Además, puede usar otras tecnologías: CORBA, ASN.1 ( herramienta ASN.1 ), UDP o TCP