RMI-Alternative SIMON

veröffentlicht am 02. September 2010

Momentan erstelle ich für ein Studienprojekt eine kleine Instant-Messenger-Lösung (Server und Client). Die Kommunikation wollte ich entweder über Sockets (per TPC oder UDP) oder RMI (Remote Method Invocation) umsetzen. Da RMI Probleme mit Firewalls hat, wenn der Server etwas an den Client senden möchte, habe ich mich zunächst für Sockets entschieden. Doch dann bekam ich von einem Freund den Tipp, dass ich mir mal SIMON angucken sollte.

SIMON ist ein API für entfernte Methodenaufrufe (Remote Procedure Calls), mit der es extrem einfach ist, Methoden entfernt auf einem Client aufzurufen. Das ist natürlich nicht der einzige Vorteil, aber für mein Projekt besonders wichtig. Wer mehr über SIMON erfahren will, sollte sich zum Beispiel den Vergleich zwischen RMI und SIMON anschauen.

Im Grunde genommen müssen nur folgende Schritte gemacht werden, um eine ordentliche Kommunikation zwischen Server und Client zu ermöglichen:

  • Interface für Server schreiben
  • Interface für Client schreiben
  • Server-Interface implementieren
  • Client-Interface implementieren

Beispielprogramm

Um euch das Ganze ein wenig näher zu bringen, habe ich ein HelloSimon-Programm vorbereitet. Zu bemerken ist, dass ich die Fehlerbehandlung bei diesem Beispiel komplett außen vor gelassen habe.

ServerInterface.java

package de.techspread.hellosimon;

import de.root1.simon.SimonRemote;
import de.root1.simon.exceptions.SimonRemoteException;

public interface ServerInterface extends SimonRemote {
   public void register(ClientInterface client) throws SimonRemoteException;
}

ClientInterface.java

package de.techspread.hellosimon;

import de.root1.simon.SimonRemote;
import de.root1.simon.exceptions.SimonRemoteException;

public interface ClientInterface extends SimonRemote {
   public void hello() throws SimonRemoteException;
}

Server.java

package de.techspread.hellosimon;

import de.root1.simon.Registry;
import de.root1.simon.Simon;
import de.root1.simon.exceptions.SimonRemoteException;

public class Server implements ServerInterface {

  private static final long serialVersionUID = 1L;
  private Registry registry;

  public static void main(String[] args) throws Exception {
    new Server();
  }

  public Server() throws Exception {
    registry = Simon.createRegistry(1234);
    registry.bind("Server", this);
  }

  @Override
  public void register(ClientInterface client) throws SimonRemoteException {
    client.hello();
    registry.unbind("Server");
    System.exit(0);
  }
}

Client.java

package de.techspread.hellosimon;

import de.root1.simon.Simon;
import de.root1.simon.exceptions.SimonRemoteException;

public class Client implements ClientInterface {

  private static final long serialVersionUID = 1L;
  private ServerInterface server;

  public static void main(String[] args) throws Exception {
    new Client();
  }

  public Client() throws Exception {
    server = (ServerInterface) Simon.lookup("localhost", 1234, "Server");
    server.register(this);
  }

  @Override
  public void hello() throws SimonRemoteException {        
    System.out.println("Hello Simon!");        
    Simon.release(server);
    System.exit(0);
  }
}

Erläuterung

Was passiert hier nun? Zunächst wird der Server gestartet. Dieser öffnet den Port 1234 auf dem eigenen Rechner und meldet sich als Dienst „Server“ an. Danach wird der Client gestartet. Dieser verbindet sich auf den eben geöffneten Port und fragt nach dem Dienst „Server“. Sobald der Client den entsprechenden Dienst übermittelt bekommen hat, öffnet dieser die entfernte register-Methode auf dem Server und übergibt eine Referenz auf sich selbst mit zum Server. Sobald die register-Methode auf dem Server aufgerufen wird, ruft der Server wiederum die hello-Methode auf dem Client auf. Danach wird die Verbindung sauber gekappt und die Programme beendet.

Wie man sieht, ist das Aufrufen von entfernten Methoden sehr einfach mit SIMON. Binnen kürzester Zeit kann man so auch komplexe netzwerkfähige Programme erstellen. Und das Beste dabei ist, dass man sich um Firewalls keine Gedanken machen muss :)

Kommentare

Gibs zu :)
Du bekommst manchmal schon gute Tipps von mir :P

Kommentar #1 von Tobias am 02. September 2010


Ja, manchmal hast du deine geistig erhabenen Momente :D

Kommentar #2 von Patrick am 02. September 2010


Nette Geschichte,
wenn ich mal wieder was Netzwerk-mässiges in Java entwickeln sollte, werd ich mir das auf jeden Fall anschauen.
Der bestechende Vorteil gegenüber RMI ist natürlich, dass nur ein Socket für die Kommunikation in beide Richtungen benötigt wird.

Kommentar #3 von Dr4K4n am 09. September 2010


Hinterlasse einen Kommentar