Suche…


Bemerkungen

RMI erfordert 3 Komponenten: Client, Server und eine gemeinsam genutzte Remote-Schnittstelle. Die gemeinsam genutzte Remote-Schnittstelle definiert den Client-Server-Vertrag durch Angabe der Methoden, die ein Server implementieren muss. Die Schnittstelle muss für den Server sichtbar sein, damit die Methoden implementiert werden können. Die Schnittstelle muss für den Client sichtbar sein, damit er weiß, welche Methoden ("Dienste") der Server bereitstellt.
Jedes Objekt, das eine Remote-Schnittstelle implementiert, übernimmt die Rolle eines Servers. Somit ist eine Client-Server-Beziehung, in der der Server auch Methoden im Client aufrufen kann, eine Server-Server-Beziehung. Dies wird als Rückruf bezeichnet, da der Server den "Client" zurückrufen kann. Aus diesem Grund ist es akzeptabel, den Designation Client für die Server zu verwenden, die als solche funktionieren.

Die gemeinsam genutzte Remote-Schnittstelle ist eine beliebige Schnittstelle, die Remote . Ein Objekt, das als Server fungiert, durchläuft Folgendes:

  1. Implementiert die freigegebene Remote-Schnittstelle entweder explizit oder implizit durch Erweiterung von UnicastRemoteObject das Remote implementiert.
  2. Exportiert, entweder implizit, wenn UnicastRemoteObject erweitert UnicastRemoteObject , oder explizit durch UnicastRemoteObject#exportObject an UnicastRemoteObject#exportObject .
  3. In eine Registry eingebunden, entweder direkt über die Registry oder indirekt über die Naming . Dies ist nur für den Aufbau der Erstkommunikation notwendig, da weitere Stubs direkt über RMI übergeben werden können.

In der Projektkonfiguration sind die Client- und Serverprojekte völlig unabhängig voneinander, aber jedes gibt ein freigegebenes Projekt in seinem Erstellungspfad an. Das freigegebene Projekt enthält die Remote-Schnittstellen.

Client-Server: Aufrufen von Methoden in einer JVM von einer anderen

Die gemeinsam genutzte Remote-Schnittstelle:

package remote;

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface RemoteServer extends Remote {

    int stringToInt(String string) throws RemoteException;
}

Der Server, der die freigegebene Remote-Schnittstelle implementiert:

package server;

import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;

import remote.RemoteServer;

public class Server implements RemoteServer {

    @Override
    public int stringToInt(String string) throws RemoteException {

        System.out.println("Server received: \"" + string + "\"");
        return Integer.parseInt(string);
    }

    public static void main(String[] args) {

        try {
            Registry reg = LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
            Server server = new Server();
            UnicastRemoteObject.exportObject(server, Registry.REGISTRY_PORT);
            reg.rebind("ServerName", server);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
}

Der Client, der eine Methode auf dem Server (remote) aufruft:

package client;

import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

import remote.RemoteServer;

public class Client {

    static RemoteServer server;

    public static void main(String[] args) {

        try {
            Registry reg = LocateRegistry.getRegistry();
            server = (RemoteServer) reg.lookup("ServerName");
        } catch (RemoteException | NotBoundException e) {
            e.printStackTrace();
        }

        Client client = new Client();
        client.callServer();
    }

    void callServer() {
    
        try {
            int i = server.stringToInt("120");
            System.out.println("Client received: " + i);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
}

Ausgabe:

Server erhalten: "120"
Kunde erhielt: 120

Callback: Aufrufen von Methoden auf einem "Client"

Überblick

In diesem Beispiel senden 2 Clients Informationen über einen Server. Ein Client sendet dem Server eine Nummer, die an den zweiten Client weitergeleitet wird. Der zweite Client halbiert die Nummer und sendet sie über den Server an den ersten Client zurück. Der erste Client macht das Gleiche. Der Server stoppt die Kommunikation, wenn die von einem der Clients zurückgegebene Nummer weniger als 10 ist. Der Rückgabewert vom Server an die Clients (die Nummer, die er in eine String-Darstellung umgewandelt hat) führt dann den Prozess zurück.

  1. Ein Anmeldeserver bindet sich an eine Registry.
  2. Ein Client sucht den Login-Server und ruft die login Methode mit seinen Informationen auf. Dann:
    • Der Anmeldeserver speichert die Clientinformationen. Es enthält den Stub des Clients mit den Rückmeldemethoden.
    • Der Anmeldeserver erstellt einen Serverstub ("Verbindung" oder "Sitzung") und gibt ihn an den zu speichernden Client zurück. Es enthält den Stub des Servers mit seinen Methoden, einschließlich einer logout (in diesem Beispiel nicht verwendet).
  3. Ein Client ruft das passInt des Servers mit dem Namen des Empfängerclients und einem int .
  4. Der Server ruft die half des Empfängerclients mit diesem int . Dadurch wird eine Hin- und Her-Kommunikation (Anrufe und Rückrufe) eingeleitet, bis der Server angehalten wird.

Die gemeinsam genutzten Remote-Schnittstellen

Der Login-Server:

package callbackRemote;

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface RemoteLogin extends Remote {

    RemoteConnection login(String name, RemoteClient client) throws RemoteException;
}

Der Server:

package callbackRemote;

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface RemoteConnection extends Remote {

    void logout() throws RemoteException;

    String passInt(String name, int i) throws RemoteException;
}

Der Kunde:

package callbackRemote;

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface RemoteClient extends Remote {

    void half(int i) throws RemoteException;
}

Die Implementierungen

Der Login-Server:

package callbackServer;

import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.HashMap;
import java.util.Map;

import callbackRemote.RemoteClient;
import callbackRemote.RemoteConnection;
import callbackRemote.RemoteLogin;

public class LoginServer implements RemoteLogin {

    static Map<String, RemoteClient> clients = new HashMap<>();

    @Override
    public RemoteConnection login(String name, RemoteClient client) {

        Connection connection = new Connection(name, client);
        clients.put(name, client);
        System.out.println(name + " logged in");
        return connection;
    }

    public static void main(String[] args) {

        try {
            Registry reg = LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
            LoginServer server = new LoginServer();
            UnicastRemoteObject.exportObject(server, Registry.REGISTRY_PORT);
            reg.rebind("LoginServerName", server);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
}

Der Server:

package callbackServer;

import java.rmi.NoSuchObjectException;
import java.rmi.RemoteException;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.rmi.server.Unreferenced;

import callbackRemote.RemoteClient;
import callbackRemote.RemoteConnection;

public class Connection implements RemoteConnection, Unreferenced {

    RemoteClient client;
    String name;

    public Connection(String name, RemoteClient client) {

        this.client = client;
        this.name = name;
        try {
            UnicastRemoteObject.exportObject(this, Registry.REGISTRY_PORT);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void unreferenced() {

        try {
            UnicastRemoteObject.unexportObject(this, true);
        } catch (NoSuchObjectException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void logout() {

        try {
            UnicastRemoteObject.unexportObject(this, true);
        } catch (NoSuchObjectException e) {
            e.printStackTrace();
        }
    }

    @Override
    public String passInt(String recipient, int i) {

        System.out.println("Server received from " + name + ":" + i);
        if (i < 10)
            return String.valueOf(i);
        RemoteClient client = LoginServer.clients.get(recipient);
        try {
            client.half(i);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        return String.valueOf(i);
    }
}

Der Kunde:

package callbackClient;

import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;

import callbackRemote.RemoteClient;
import callbackRemote.RemoteConnection;
import callbackRemote.RemoteLogin;

public class Client implements RemoteClient {

    RemoteConnection connection;
    String name, target;

    Client(String name, String target) {

        this.name = name;
        this.target = target;
    }

    public static void main(String[] args) {

        Client client = new Client(args[0], args[1]);
        try {
            Registry reg = LocateRegistry.getRegistry();
            RemoteLogin login = (RemoteLogin) reg.lookup("LoginServerName");
            UnicastRemoteObject.exportObject(client, Integer.parseInt(args[2]));
            client.connection = login.login(client.name, client);
        } catch (RemoteException | NotBoundException e) {
            e.printStackTrace();
        }

        if ("Client1".equals(client.name)) {
            try {
                client.connection.passInt(client.target, 120);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void half(int i) throws RemoteException {

        String result = connection.passInt(target, i / 2);
        System.out.println(name + " received: \"" + result + "\"");
    }
}

Das Beispiel ausführen:

  1. Führen Sie den Login-Server aus.
  2. Führen Sie einen Client mit den Argumenten Client2 Client1 1097 .
  3. Führen Sie einen Client mit den Argumenten Client1 Client2 1098 .

Die Ausgänge erscheinen in 3 Konsolen, da es 3 JVMs gibt. hier sind sie zusammengeworfen:

Client2 ist angemeldet
Client1 angemeldet
Server erhielt von Client1: 120
Server erhalten von Client2: 60
Server erhielt von Client1: 30
Server erhalten von Client2: 15
Server erhalten von Client1: 7
Client1 erhielt: "7"
Client2 erhalten: "15"
Client1 erhielt: "30"
Client2 erhalten: "60"

Einfaches RMI-Beispiel mit Client- und Server-Implementierung

Dies ist ein einfaches RMI-Beispiel mit fünf Java-Klassen und zwei Paketen ( Server und Client) .

Server-Paket

PersonListInterface.java

public interface PersonListInterface extends Remote
{
    /**
     * This interface is used by both client and server
     * @return List of Persons
     * @throws RemoteException
     */
    ArrayList<String> getPersonList() throws RemoteException;
}

PersonListImplementation.java

public class PersonListImplementation 
extends UnicastRemoteObject 
implements PersonListInterface
{

    private static final long serialVersionUID = 1L;

    // standard constructor needs to be available
    public PersonListImplementation() throws RemoteException
    {}

    /**
     * Implementation of "PersonListInterface"
     * @throws RemoteException
     */
    @Override
    public ArrayList<String> getPersonList() throws RemoteException
    {
        ArrayList<String> personList = new ArrayList<String>();
        
        personList.add("Peter Pan");
        personList.add("Pippi Langstrumpf");
        // add your name here :)
        
        return personList;
    }
}

Server.java

public class Server {

    /**
     * Register servicer to the known public methods
     */
    private static void createServer() {
        try {
            // Register registry with standard port 1099
            LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
            System.out.println("Server : Registry created.");

            // Register PersonList to registry 
            Naming.rebind("PersonList", new PersonListImplementation());
            System.out.println("Server : PersonList registered");

        } catch (final IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(final String[] args) {
        createServer();
    }
}

Client-Paket

PersonListLocal.java

public class PersonListLocal {
    private static PersonListLocal instance;
    private PersonListInterface personList;

    /**
     * Create a singleton instance
     */
    private PersonListLocal() {
        try {
            // Lookup to the local running server with port 1099
            final Registry registry = LocateRegistry.getRegistry("localhost",
                    Registry.REGISTRY_PORT);

            // Lookup to the registered "PersonList"
            personList = (PersonListInterface) registry.lookup("PersonList");
        } catch (final RemoteException e) {
            e.printStackTrace();
        } catch (final NotBoundException e) {
            e.printStackTrace();
        }
    }

    public static PersonListLocal getInstance() {
        if (instance == null) {
            instance = new PersonListLocal();
        }

        return instance;
    }

    /**
     * Returns the servers PersonList
     */
    public ArrayList<String> getPersonList() {
        if (instance != null) {
            try {
                return personList.getPersonList();
            } catch (final RemoteException e) {
                e.printStackTrace();
            }
        }

        return new ArrayList<>();
    }
       }

PersonTest.java

public class PersonTest
{
    public static void main(String[] args)
    {
        // get (local) PersonList 
        ArrayList<String> personList = PersonListLocal.getInstance().getPersonList();
        
        // print all persons
        for(String person : personList)
        {
            System.out.println(person);
        }
    }
}

Testen Sie Ihre Bewerbung

  • Starten Sie die Hauptmethode von Server.java. Ausgabe:
Server : Registry created.
Server : PersonList registered
  • Starten Sie die Hauptmethode von PersonTest.java. Ausgabe:
Peter Pan
Pippi Langstrumpf


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow