Válí se ti projekty v šuplíku? Dostaň je mezi lidi a získej cool tričko a body na profi IT kurzy v soutěži ITnetwork summer 2017!
Přidej si svou IT školu do profilu a najdi spolužáky zde na síti :)

3. díl - Java RMI - Volání ze serveru na portu 2020

Java Pro pokročilé RMI Java RMI - Volání ze serveru na portu 2020

ONEbit hosting Unicorn College Tento obsah je dostupný zdarma v rámci projektu IT lidem. Vydávání, hosting a aktualizace umožňují jeho sponzoři.

V minulé lekci kurzu o RMI v Javě 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

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

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

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

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

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

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

RMI server spustíme

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

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

V příštím díle si probereme trochu další teorie ohledně RMI.


 

Stáhnout

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

 

 

Článek pro vás napsal Robert Michalovič
Avatar
Jak se ti líbí článek?
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-michalovi%C4%8D-8a9b9498
Miniatura
Předchozí článek
Java RMI - Volání void metod
Miniatura
Všechny články v sekci
RMI - Remote Method Invocation
Aktivity (2)

 

 

Komentáře

Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zatím nikdo nevložil komentář - buď první!