2009-11-05 13 views
40

Szukam dwóch osobnych (ale powiązanych) aplikacji Java na komputer.Komunikacja między dwiema oddzielnymi aplikacjami Java na komputery stacjonarne

Chcę, aby jedna aplikacja wyzwoliła drugą, przekazując dane, które następnie można edytować i przekazywać, tj. Komunikacja będzie dwukierunkowa. Jeśli druga aplikacja już działa, chcę, żeby po prostu się komunikują, tzn. Nie chcę po prostu przekazywać argumentów przez linię poleceń itp.

Ogólnie rzecz biorąc, jakie strategie/techniki powinienem badać, aby osiągnąć ten cel ?

+1

Świetne pytanie. Czy kiedykolwiek wdrożyłeś to? –

+0

Jeszcze nie ... to były bardzo wstępne badania nad nadchodzącym projektem :) – William

+1

Czy osoby głosujące na ponowne otwarcie wyrażają swoje uzasadnienie? –

Odpowiedz

19

Aby pokazać, jak łatwo można komunikować się ze sobą w dwóch aplikacjach, sprawdź to demo sieciowego schowka przy użyciu JGroups. Po prostu uruchom dwie instancje i rozpocznij upuszczanie plików do jednego z nich.Druga instancja natychmiast pokaże te same pliki.

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

Hi @mhaller Chciałem wiedzieć, czy istnieje jakiś konkretny powód, dla którego użyłeś 'throws' w metodzie' main', ponieważ metoda 'main' jest specyficzną metodą, którą otoczyliśmy słowem' try catch'. Proszę opracuj. – Vishrant

+0

@Vishrant - byłem po prostu leniwy. dozwolone jest używanie "rzutów" dla głównej metody, nie ma znaczenia. Często też deklaruję "throws Exception" dla testów jednostkowych, więc nie muszę osobno obsługiwać wszystkich sprawdzanych wyjątków. – mhaller

+0

dziękuję za odpowiedź, głównie używam słowa kluczowego 'throws' gdy jest jakiś kontener jak w' rozpórkach' ale podczas gdy piszę metodę 'main' w mojej aplikacji (która jest specyficzną metodą nie powszechną) używam bloku' try catch' radzić sobie z 'Wyjątkiem' na swój własny sposób. Tak, używając 'throws' w metodzie' main' robi różnicę jeśli wystąpi 'wyjątek' w metodzie' main' zostanie wywołany do 'JVM' i twój program się zatrzyma, również' JVM' obsłużyło 'Wyjątek' we własnym droga. 'throws' jest pojęciem' re-throwing Exception', które jest używane w 'Common Methods' (metodach używanych przez wiele klas). – Vishrant

18

Każdy z nich mógł słuchać na Socket. This tutorial jest dobry do rozpoczęcia.

+0

Czy to zwyczajny sposób na zrobienie tego lub RMI? A raczej jaka jest różnica? – Pacerier

+0

@Pacerier - Gniazda są sposobem na przesłanie bajtów do stosu sieciowego. RMI pozwala na wywoływanie metod obiektów, które istnieją w innej maszynie JVM, wymiana danych jest nieprzejrzysta dla RMI, ale nadal może używać gniazd pod spodem. – Xailor

+0

Ic, więc gniazda są najlepsze niż proste i szybkie – Pacerier

2

Aby wszystko było proste, dlaczego nie używać zwykłych gniazd TCP?

+0

Zwykłe gniazda TCP nie definiują protokołu, nie serializują obiektów ani nie oferują między innymi odzyskiwania po błędzie. Musisz sam zająć się wszystkim. Oczywiście, że RMI nie jest dużo lepszy! –

+0

Ale jeśli dane są proste, to nie jest wielka sprawa, aby sobie z tym poradzić i nie musisz zawracać sobie głowy dodatkowymi konfiguracjami, takimi jak rejestry RMI. – Mark

+0

@ Zaznacz, jakie są inne alternatywy niskiego poziomu? Czy tcp/ip jest jedynym sposobem przesyłania danych między dwoma programami na ** tej samej maszynie? – Pacerier

8

Należy również wziąć pod uwagę dobry klasyczny RMI.

+0

Czy to zwykle jest podejście, gdy chcę mieć dwa różne procesy? – Pacerier

+0

Jest to elementarny sposób przekazywania obiektów Javy między JVM (często jako różne procesy). Można również współużytkować odwołania do obiektów, aby działać na obiektach zdalnych w innej maszynie JVM.Oczywiście cała struktura EJB i frameworki nieudane próbują odciągnąć RMI, ale jest to prawdziwe podejście do współdzielonych obiektów współdzielonych wielu JVM. Aby być uczciwym, jest to sposób wywoływania metod zdalnych, ale większość metod i tak zwraca lub jest przekazywana. – Xailor

4

Spróbuj komunikować się z SocketCommunication, nawet jeśli aplikacja znajduje się na tym samym komputerze.

Tutaj można znaleźć więcej informacji o how to do it (dokumentacja Sun/Java).

1

Po drugie połączenie z gniazdem i RMI. RMI jest nieco bardziej zaangażowany, ale jest bardziej intuicyjny dla programisty. Zależy to od rodzaju wysyłanych informacji. Popychanie surowe bajty na innej maszynie może więcej sensu następnie uruchomić serwer RMI i radzenia sobie z tym wszystkim jazz ...

4
  • „Enterprise” sposób, aby przejść byłoby uruchomić te aplikacje na serwerze Java EE lub przynajmniej w ramach Spring. To także prawdopodobnie ogromna przesada.

  • Jeśli trzeba przekazać kilka danych, RMI to zrobi.

  • Jeśli nie boisz się włamać do własnego protokołu, struktury danych i obsługi błędów, możesz skonfigurować gniazda dla serwerów i klientów i komunikować się za ich pośrednictwem.

  • Myślę, że istnieje pewna nieuporządkowana prośba o alternatywę komunikowania się za pośrednictwem pliku we wspólnym katalogu (konfigurowanie własnego protokołu, kto zapisuje lub usuwa plik w momencie), lub za pośrednictwem wspólnej bazy danych. Niski poziom techniki, niezbyt szybki, ale bardzo prosty i niezawodny. I dość łatwo jest monitorować "komunikację" z zewnątrz.

6

Wystarczy popatrzeć na JavaGroups będzie rozwiązać problem komunikacyjny, a także pomóc wykryć, czy druga aplikacja jest uruchomiona. Jeśli aplikacja nie jest uruchomiona, musisz uruchomić nową maszynę JVM za pomocą java.lang.Runtime.exec() ...

+1

+1 dla JGroups, uwielbiam to. FYI wiesz, że ta strona ma 10 lat i ten sam kod został przyjęty przez JBoss od lat? Zobacz jgroups.org – mhaller

0

W zależności od stylu komunikacji, której szukasz (duże opóźnienie, wiele danych itp.) i czy system ten może rozszerzyć się poza zwykłe 2 systemy java, może to być system przesyłania wiadomości wykorzystujący rozwiązanie warstwy pośredniej, takie jak Tibco SmartSockets.

Przydałoby się więcej informacji na temat konfiguracji i oczekiwań.

1

Zależy od rodzaju komunikacji między dwiema aplikacjami. Jeśli używasz na przykład gniazd lub RMI, obie aplikacje muszą być zainstalowane, aby komunikacja mogła się odbyć. Jeśli rodzaj komunikacji, którą chcesz wykonać, może być bardziej asynchroniczny, możesz użyć bardziej opartego na komunikacji podejścia.

Na przykład, ZooKeeper pozwala zaimplementować praktycznie wszystko, co tylko chcesz, na prostych, ale potężnych prymitywach. Ta strona (http://hadoop.apache.org/zookeeper/docs/current/recipes.html) wyjaśnia, w jaki sposób budować konstrukty wyższego poziomu w ZooKeeper.

Wadą jest to, że potrzebujesz innego systemu. Jeśli korzystasz na przykład z JGroups, to nie.

Nadzieja to pomaga

19

To zależy jak chcesz komunikować te 2 programy:

  • Jeśli potrzebujesz tylko semafory między procesami, utwórz plik gdzieś w/tmp i zablokować go.

  • Jeśli potrzebujesz tylko komunikacji synchronicznej między procesami (zdalne wywoływanie procedur), RMI powinien być najłatwiejszy.

  • Jeśli potrzebujesz asynchronicznej komunikacji międzyprocesowej, JMS powinien być najłatwiejszy.

  • Jeśli potrzebujesz pamięci współdzielonej między procesami, użyj zmapowanych plików. Jeśli potrzebujesz wszystkich powyższych, Terracotta (http://www.terracotta.org/) jest najprostszym sposobem: programy Java na różnych maszynach JVM na tych samych lub nawet różnych komputerach widzą się nawzajem, jakby były wykonane wewnątrz jednej JVM na jednej maszynie. Podział jednego programu na kilka nie wymaga nawet zmian kodu - wystarczy napisać plik konfiguracyjny XML.

Powiązane problemy