2009-11-05 18 views
40

Estoy buscando desarrollar dos aplicaciones de escritorio Java separadas (pero relacionadas).Comunicación entre dos aplicaciones de escritorio Java separadas

Deseo que una aplicación active la otra, ingresando datos que luego pueden ser editados y transmitidos, es decir, la comunicación será bidireccional. Si la otra aplicación ya se está ejecutando, quiero que se comuniquen, es decir, no quiero simplemente pasar argumentos por la línea de comandos, etc.

Hablando en general, ¿qué estrategias/técnicas debería considerar para lograr esto? ?

+1

Gran pregunta. ¿Alguna vez implementaste esto? –

+0

Todavía no ... esta fue una investigación muy inicial para un próximo proyecto :) – William

+1

¿Puede la gente que vota reabrir expresar su razonamiento? –

Respuesta

19

Para mostrar lo fácil que es permitir que dos aplicaciones se comuniquen entre sí, consulte esta demostración de portapapeles de red mediante JGroups. Simplemente inicie dos instancias y empiece a colocar archivos en uno de ellos.La segunda instancia mostrará instantáneamente los mismos archivos.

import java.io.Serializable; 
import java.awt.*; 
import java.awt.datatransfer.*; 
import javax.swing.*; 
import org.jgroups.*; 

public class JGroupsTest { 

    public static void main(String[] args) throws Exception { 
     final JFrame frame = new JFrame(); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setVisible(true); 
     frame.setSize(500, 300); 
     final DefaultListModel listModel = new DefaultListModel(); 
     final JList panel = new JList(listModel); 
     panel.setBackground(new Color(128, 0, 40)); 
     panel.setForeground(new Color(240, 240, 240)); 
     frame.add(panel); 
     System.setProperty("java.net.preferIPv4Stack", "true"); 
     final JChannel channel = new JChannel("udp.xml"); 
     channel.connect("networkclipboard"); 
     channel.setReceiver(new ReceiverAdapter() { 
      @Override 
      public void viewAccepted(View newView) { 
       frame.setTitle("Network Clipboard - " + channel.getLocalAddress()); 
      } 

      @Override 
      public void receive(Message msg) { 
       listModel.addElement(msg.getObject()); 
      } 
     }); 

     panel.setTransferHandler(new TransferHandler() { 
      @Override 
      public boolean importData(JComponent comp, Transferable t) { 
       DataFlavor[] transferDataFlavors = t.getTransferDataFlavors(); 
       for (DataFlavor flavor : transferDataFlavors) { 
        try { 
         Object data = t.getTransferData(flavor); 
         if (data instanceof Serializable) { 
          Serializable serializable = (Serializable) data; 
          Message msg = new Message(); 
          msg.setObject(serializable); 
          channel.send(msg); 
         } 
        } catch (Exception e) { 
         e.printStackTrace(); 
        } 
       } 
       return super.importData(comp, t); 
      } 

      @Override 
      public boolean canImport(TransferSupport support) { 
       return true; 
      } 

      @Override 
      public boolean canImport(JComponent comp, DataFlavor[] transferFlavors) { 
       return true; 
      } 

     }); 
    } 

} 
+0

Hola, @mhaller, quería saber si hay algún motivo específico por el que hayas usado 'throws' en el método' main' ya que 'main' method es un método específico que lo rodeamos con' try catch'. Por favor elabora. – Vishrant

+0

@Vishrant - solo estaba siendo flojo. está permitido usar 'throws' para el método principal, no hace la diferencia. también a menudo declaro 'throws Exception' para pruebas unitarias, por lo que no tengo que manejar todas las excepciones marcadas de forma individual. – mhaller

+0

gracias por responder, utilizo principalmente la palabra clave 'throws' cuando hay algún contenedor como' struts', pero mientras escribo el método 'main' en mi aplicación (que es un método específico, no es un método común) utilizo el bloque' try catch' para manejar 'Exception' a mi manera. Sí, el uso de 'throws' en el método' main' hace la diferencia si se produce 'Exception' en el método' main', se lanzará a 'JVM' y tu programa se detendrá, y los manejadores' JVM' lanzarán 'Exception' en sí mismo camino. 'throws' es un concepto de' re-throwing Exception' que se usa en 'Common Methods' (métodos que son utilizados por muchas clases). – Vishrant

18

Podrían cada uno escuchar en un Socket. This tutorial es bueno para comenzar.

+0

¿Es esta la forma habitual de hacerlo o RMI? O más bien, ¿cuál es la diferencia? – Pacerier

+0

@Pacerier: los sockets son una forma de transmitir bytes a una pila de red. RMI permite llamar a métodos de objetos que existen en una JVM diferente, el intercambio de datos es opaco para RMI aunque todavía puede usar conectores debajo. – Xailor

+0

Ic, por lo que los sockets son los mejores, ya que sus simples y rápidos – Pacerier

2

Para mantener las cosas simples, ¿por qué no solo usar enchufes TCP simples?

+0

conectores TCP simples no definen un protocolo, serializan objetos ni ofrecen recuperación de errores, entre otras cosas. Tienes que encargarte de todo tú mismo. ¡No es que RMI sea mucho mejor, por supuesto! –

+0

Pero si los datos son simples, no es un gran problema manejar esto y no tiene que preocuparse por la configuración adicional de cosas como RMI registrys. – Mark

+0

@Mark ¿qué otras alternativas de bajo nivel existen? ¿O es tcp/ip la única forma de transferir datos entre dos programas en la ** misma ** máquina? – Pacerier

8

También debería considerar la buena RMI clásica.

+0

¿Suele ser este el enfoque cuando quiero tener dos procesos diferentes? – Pacerier

+0

Es la forma elemental de pasar objetos Java hacia adelante y hacia atrás entre las JVM (a menudo como procesos diferentes). También puede compartir referencias de objetos para actuar sobre objetos remotos en la otra JVM.Por supuesto, todo el conjunto de herramientas EJB y frameworks intentan abstraer RMI, pero es un enfoque verdadero para los objetos compartidos multi-JVM compartidos. Para ser justos, es una forma de invocar métodos remotos, pero la mayoría de los métodos devuelven o se pasan objetos de todos modos. – Xailor

4

Trate de comunicarse con SocketCommunication, incluso si la aplicación está en la misma máquina.

Aquí puede encontrar más información sobre how to do it (documentación de Sun/Java).

1

I segundo Socket communication and RMI. RMI está un poco más involucrado pero es más intuitivo para un programador. Sin embargo, depende del tipo de información que esté enviando. Empujar bytes sin más a otra máquina podría tener más sentido a continuación, se ejecuta el servidor RMI y hacer frente a todo ese jazz ...

4
  • La forma "Empresa" ir, sería ejecutar estas aplicaciones en un servidor Java EE o al menos en un marco de primavera. También es probablemente demasiado exagerado.

  • Si es necesario comunicar una gran cantidad de datos, RMI lo hará.

  • Si no tiene miedo de hackear su propio protocolo, estructura de datos y manejo de errores, puede configurar los sockets del servidor y del cliente y comunicarse a través de ellos.

  • Creo que hay un cierto atractivo básico para la alternativa de comunicarse a través de un archivo en un directorio común (configurar su propio protocolo de quién escribe o borra el archivo cuando), o a través de una base de datos compartida. Baja tecnología, no extremadamente rápido, pero muy simple y confiable. Y es bastante fácil controlar la "comunicación" desde el exterior.

6

Tenga una mirada en JavaGroups, que va a resolver su problema de comunicación y también ayudará a detectar si la otra aplicación se está ejecutando. Si la aplicación no se está ejecutando, deberá iniciar una nueva JVM con java.lang.Runtime.exec() ...

+1

+1 para JGroups, me encanta. ¿Le parece que esta página tiene 10 años y que JBoss ha adoptado el mismo código desde hace años? Ver jgroups.org – mhaller

0

Dependiendo del estilo de comunicación que esté buscando (alta latencia, mucho) de datos, etc.) y si este sistema puede expandirse simplemente a través de 2 sistemas java, una posibilidad podría ser un sistema de mensajería que use una solución de middleware como Tibco SmartSockets.

Cualquier información adicional sobre su configuración y expectativas ayudaría.

1

Depende del tipo de comunicación que desee hacer entre las 2 aplicaciones. Si usa conectores o RMI, por ejemplo, ambas aplicaciones deben estar activadas para que la comunicación se realice. Si el tipo de comunicación que desea hacer puede ser más asincrónico, entonces puede usar más de un enfoque basado en mensajes.

Por ejemplo, ZooKeeper le permite implementar casi cualquier cosa que desee además de primitivas simples pero potentes. Esta página (http://hadoop.apache.org/zookeeper/docs/current/recipes.html) explica cómo construir construcciones de alto nivel con ZooKeeper.

El inconveniente es que necesita otro sistema. Si usa JGroups por ejemplo, entonces no.

Esperanza esto ayuda

19

Depende de cómo le gustaría comunicar esos 2 programas:

  • Si necesita sólo semáforos entre procesos, crear un archivo en algún lugar en/tmp y bloquearlo.

  • Si solo necesita mensajería síncrona entre procesos (llamada a procedimiento remoto), la RMI debería ser más fácil.

  • Si necesita mensajería entre procesos asíncrona, JMS debería ser lo más fácil.

  • Si necesita memoria compartida entre procesos, use los archivos asignados.

  • Si necesita todo lo anterior, Terracotta (http://www.terracotta.org/) es la forma más fácil: los programas Java en diferentes JVM en el mismo o incluso diferentes equipos se ven como si se hubieran ejecutado dentro de una JVM en una máquina. Dividir un programa en unos pocos ni siquiera requiere ningún cambio de código: es suficiente para escribir un archivo de configuración XML.

Cuestiones relacionadas