Java Language Callback: invocazione di metodi su un "client"


Esempio

Panoramica

In questo esempio 2 client inviano informazioni reciprocamente attraverso un server. Un client invia al server un numero che viene inoltrato al secondo client. Il secondo client dimezza il numero e lo invia al primo client attraverso il server. Il primo cliente fa lo stesso. Il server interrompe la comunicazione quando il numero restituito da uno dei client è inferiore a 10. Il valore restituito dal server ai client (il numero convertito in rappresentazione stringa) quindi retrocede il processo.

  1. Un server di login si lega a un registro.
  2. Un client cerca il server di login e chiama il metodo di login con le sue informazioni. Poi:
    • Il server di login memorizza le informazioni del cliente. Include lo stub del cliente con i metodi di callback.
    • Il server di login crea e restituisce un server stub ("connessione" o "sessione") al client da memorizzare. Include lo stub del server con i suoi metodi incluso un metodo di logout (non utilizzato in questo esempio).
  3. Un client chiama il passInt del server con il nome del client del destinatario e un int .
  4. Il server chiama la half sul client destinatario con quella int . Ciò avvia una comunicazione avanti e indietro (chiamate e callback) finché non viene arrestata dal server.

Le interfacce remote condivise

Il server di login:

package callbackRemote;

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

public interface RemoteLogin extends Remote {

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

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

Il cliente:

package callbackRemote;

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

public interface RemoteClient extends Remote {

    void half(int i) throws RemoteException;
}

Le implementazioni

Il server di login:

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

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

Il cliente:

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 + "\"");
    }
}

Esecuzione dell'esempio:

  1. Esegui il server di login.
  2. Esegui un client con gli argomenti Client2 Client1 1097 .
  3. Esegui un client con gli argomenti Client1 Client2 1098 .

Le uscite appariranno su 3 console poiché ci sono 3 JVM. eccoli raggruppati insieme:

Client2 registrato
Client1 loggato
Server ricevuto da Client1: 120
Server ricevuto da Client2: 60
Server ricevuto da Client1: 30
Server ricevuto da Client2: 15
Server ricevuto da Client1: 7
Client1 ricevuto: "7"
Client2 ricevuto: "15"
Client1 ricevuto: "30"
Client2 ricevuto: "60"