Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Lekce 3 - Java RMI - Volání ze serveru na portu 2020

V minulé lekci kurzu o RMI v Javě,Java RMI - Volání void metod, jsme si zavolali vzdálenou metodu na serveru.

V dnešní lekci si vyzkoušíme použití nedefaultního portu. V našem případě použijeme RMI registry na portu 2020. Prakticky se jedná o RMI registry, které jsme si vytvořili v dílu nastavení prostředí. Ovšem pozor, je nutné nezapomenout, že RMI registry nastavujeme pro daný projekt (Working directory). Jinak bude aplikace padat. V tomto příkladu bude mít každá třída (server i klient) používající RMI jak svůj skeleton tak i stub toho druhého.

Nastavíme RMI registry na port 2020 - RMI - Remote Method Invocation

Tento příklad tedy bude podobný příkladu v předchozí lekci, ovšem využijeme jiný port pro RMI registry, vyzkoušíme si volání ze serveru na klienta/z klienta na server. Opět se bude jednat o konzolovou aplikaci konceptu server/klient. Vše budeme simulovat na localhostu. Celý postup se prakticky opět skládá ze 4 kroků, které si zde uvedeme.

  • Naprogramujeme si rozhraní pro sdílené objekty, které budeme přes RMI sdílet
  • Naprogramujeme serverovou část, spustíme RMI registry a spustíme server
  • Naprogramujeme klientskou část a spustíme klienta
  • Sledujeme a kontrolujeme výstupy

Programování rozhraní pro sdílené objekty

Opětovně naprogramujeme rozhraní, které bude zděděno od rozhraní java.rmi.Remote. Klient musí implementovat dvě metody a server pouze jednu.

Vytvoříme rozhraní poděděné od Remote - RMI - Remote Method Invocation

Rozhraní pro klienta:

package rozhrani.klient;

public interface RozhraniKlient extends java.rmi.Remote {
    void volameKlientMetoda1() throws java.rmi.RemoteException;
    void volameKlientMetoda2() throws java.rmi.RemoteException;
}

Rozhraní pro server:

package rozhrani.server;

public interface RozhraniServer extends java.rmi.Remote {
    void volameServerMetoda1() throws java.rmi.RemoteException;
}

Programování serverové části, spuštění RMI registry a spuštění serveru

Opětovně si naprogramujeme server (např. class ServerRMI), který bude implementovat sdílené rozhraní, které jsme napsali výše. Z implementovaného rozhraní nám vznikla povinnost doprogramovat vnitřek jediné metody "volameServer­Metoda1()". Zdrojový kód serveru jsem napsal bez importů, můžete si je dodat a kód tak zjednodušit.

/*  Program potřebuje registry na defaultním portu 2020  */
package server;

public class ServerRMI implements rozhrani.server.RozhraniServer {
    private static rozhrani.server.RozhraniServer rozhrServer = null;
    private static java.rmi.registry.Registry registry = null;

    public void volameServerMetoda1() throws java.rmi.RemoteException {
        System.out.println("Metoda zavolana na serveru");
        try {
            Thread.sleep(5000); // uspíme vlákno na 5 sekund
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Zavolame metody na klientovi");
        rozhrani.klient.RozhraniKlient rozhObjektKlient= null;
        try {
            rozhObjektKlient = (rozhrani.klient.RozhraniKlient) registry.lookup("KlientRMI");
        } catch (java.rmi.RemoteException | java.rmi.NotBoundException e) {
            System.out.println("Nepodarilo se ziskat objekt stubu (rozhrani)");
            e.printStackTrace();
        }
        System.out.println("Zavolame si metody na klientech");
        try {
            rozhObjektKlient.volameKlientMetoda1();
            rozhObjektKlient.volameKlientMetoda2();
        } catch (java.rmi.RemoteException e) {
            System.out.println("Nepodarilo se zavolat metodu na klientovi");
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        System.out.println("Spustime RMI server");
        // vytvoříme objekt rozhraní (tzv. skeleton)
        try {
            rozhrServer = (rozhrani.server.RozhraniServer) java.rmi.server.UnicastRemoteObject.exportObject(new ServerRMI(),0);
        } catch (java.rmi.RemoteException e) {
            System.out.println("Nepodarilo se nam vytvorit skeleton");
            e.printStackTrace();
        }
        // získáme objekt RMI registru pro daný port
        try {
            registry = java.rmi.registry.LocateRegistry.getRegistry(2020);
        } catch (java.rmi.RemoteException e) {
            System.out.println("Nepodarilo se ziskat objekt RMI registru");
            e.printStackTrace();
        }
        // nahrajeme skeleton do registru
        try {
            registry.bind("ServerRMI",rozhrServer);
        } catch (java.rmi.RemoteException | java.rmi.AlreadyBoundException e) {
            System.out.println("Nepodarilo se nahrat skeleton do registru");
            e.printStackTrace();
        }
        System.out.println("Cekame na volani Klienta");
    }
}

Zde si rozebereme co vlastně zdrojový kód dělá. V první části (public static void main() metodě) si vytvoříme objekt (instanci) třídy implementující sdílené rozhraní. Poté získáme objekt RMI registru a již jen nahrajeme sdílený objekt do RMI registrů. Tímto způsobíme vznik tzv. skeleton. Skeleton pojmenujeme, přesněji mu přiřadíme identifikátor, "ServerRMI". Samozřejmě jméno identifikátoru je volitelné a takových skeletonů můžeme nahrát do RMI registrů kolik chceme. Nejsem si vědom omezení co se týká počtu nahraných skeletonů. Zajisté jste si všimli, že metoda získání RMI registrů má tentokrát parametr 2020. Ano, tento parametr specifikuje port (více viz Java dokumentace). Teoreticky bychom mohli i vyzkoušet spustit více RMI registrů na různých portech a do nich nahrát jiné skeletony, ale co z toho? Fungovat by to nejspíše mělo. Metoda volameServerMe­toda1() je metodou, která je k dispozici stubu na klientovi. Pokud ji zavolá, pak v metodě vytvoříme stub klienta a tím získáme metody, které má sdílený objekt na klientovi k dispozici.

RMI Java server - RMI - Remote Method Invocation

Zde si celý kód ukážeme v IDE. V druhé části (volameServer­Metoda1() metodě) se provede nejdříve uspání na 5 sekund, poté si vytvoříme zrcadlový objekt stubu klienta a zavoláme obě jeho metody, které jsou (budou) na klientovi k dispozici. Zpoždění 5 sekund je tam jen abyste přepnuli výpis konzole v IDE a mohli se přesvědčit o výpisu na klientovi na vlastní oči.

Zajisté jste si všimli, že kód je navržen tak, že se spustí server, poté klient, klient zavolá metodu na serveru a v ní se zas zavolají metody na klientovi. Samozřejmě, mohl jsem to udělat na přímo bez té sdílené metody na serveru, kdy server přímo vytvoří stub klienta, ale chtěl jsem, abychom si to vyzkoušeli.

Server RMI Java komplet - RMI - Remote Method Invocation

Programování klientské části a uspání klienta

Jako další vytvoříme třídu klienta (např. class KlientRMI). Jak jste si všimli, jedná se o standardní public static void main() metodu a je třeba ji tak i spustit.

RMI Klient - RMI - Remote Method Invocation

Kód je skutečně velmi jednoduchý a je velmi analogický s tím ze serveru. Nejdříve vytvoříme skeleton klienta, získáme RMI registry z portu 2020 a pak skeleton nahrajeme s identifikátorem "KlientRMI" do RMI registru. Po tomto je skeleton klienta k dispozici všem, kdo disponují rozhraním.

Dále vytvoříme sdílený objekt rozhraní serveru (tzv. stub) přes RMI registry. K tomu potřebujeme identifikátor, který jsme použili na serveru v RMI registrech. No a poté konečně máme objekt, který disponuje naší metodou, kterou jsme si definovali v rozhraní.

package klient;
import java.rmi.*;
import java.rmi.registry.*;
import rozhrani.klient.*;
import rozhrani.server.*;

public class KlientRMI implements RozhraniKlient {
    private static RozhraniKlient rozhrKlient;

    public void volameKlientMetoda1() throws RemoteException {
        System.out.println("Klient RMI metoda1");
    }

    public void volameKlientMetoda2() throws RemoteException {
        System.out.println("Klient RMI metoda2");
    }

    public static void main(String[] args) {
        System.out.println("Spustime RMI klienta");
        // vytvoříme objekt implementující rozhraní (tzv. skeleton)
        try {
            rozhrKlient = (RozhraniKlient) java.rmi.server.UnicastRemoteObject.exportObject(new KlientRMI(),0);
        } catch (java.rmi.RemoteException e) {
            System.out.println("Nepodarilo se nam vytvorit skeleton");
            e.printStackTrace();
        }
        // získáme objekt RMI registru pro daný port
        Registry registry = null;
        try {
            registry = LocateRegistry.getRegistry(2020);    }
        catch (RemoteException e) {
            System.out.println("Nepodarilo se ziskat objekt registru");
            e.printStackTrace();
        }
        // nahrajeme stub do registru
        try {
            registry.bind("KlientRMI",rozhrKlient);
        } catch (java.rmi.RemoteException | java.rmi.AlreadyBoundException e) {
            System.out.println("Nepodarilo se nahrat stub do registru");
            e.printStackTrace();
        }
        // zavoláme metodu na serveru
        RozhraniServer rozhObjektServer = null;
        try {
            rozhObjektServer = (RozhraniServer) registry.lookup("ServerRMI");
        } catch (RemoteException | NotBoundException e) {
            System.out.println("Nepodarilo se ziskat objekt stubu (rozhrani)");
            e.printStackTrace();
        }
        System.out.println("Zavolame si metodu na serveru");
        try {
            rozhObjektServer.volameServerMetoda1();
        } catch (RemoteException e) {
            System.out.println("Nepodarilo se zavolat metodu na serveru");
            e.printStackTrace();
        }
        System.out.println("Cekame na volani Serveru");
    }
}

Nyní si spustíme opětovně RMI registry na portu 2020.

RMI registry spustíme - RMI - Remote Method Invocation

Spustíme i server a prohlédneme si výpis na konzole.

RMI server spustíme - RMI - Remote Method Invocation

Nyní si spustíme klienta a prohlédneme si výpis na konzole. Přepneme na server a podíváme se na výpis konzole.

RMI klient spustíme - RMI - Remote Method Invocation

No a nyní se zas přepneme se na výpis konzole klienta. Krásně jde vidět zavolané metody na klientovi.

RMI výsledek - RMI - Remote Method Invocation

V příštím díle, Java RMI - Vysvětlení pojmů a popis tříd, si probereme trochu další teorie ohledně RMI.


 

Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.

Stáhnout

Stažením následujícího souboru souhlasíš s licenčními podmínkami

Staženo 7x (6.65 kB)
Aplikace je včetně zdrojových kódů v jazyce Java

 

Předchozí článek
Java RMI - Volání void metod
Všechny články v sekci
RMI - Remote Method Invocation
Přeskočit článek
(nedoporučujeme)
Java RMI - Vysvětlení pojmů a popis tříd
Článek pro vás napsal Robert Michalovič
Avatar
Uživatelské hodnocení:
Ještě nikdo nehodnotil, buď první!
Programuji převážně v Javě SE,EE a trochu nativním C a CUDA. více viz.https://cz.linkedin.com/in/robert-michalovic
Aktivity