John Squirrels
స్థాయి
San Francisco

జావా RMI

సమూహంలో ప్రచురించబడింది
హాయ్! ఈ రోజు మనం ఆసక్తికరమైన అంశాన్ని పరిశీలిస్తాము: జావా RMI. ఇది రిమోట్ మెథడ్ ఆహ్వానాన్ని సూచిస్తుంది. రెండు ప్రోగ్రామ్‌లు వేర్వేరు కంప్యూటర్‌లలో ఉన్నప్పటికీ ఒకదానితో ఒకటి కమ్యూనికేట్ చేసుకోవడానికి మీరు RMIని ఉపయోగించవచ్చు. అది చల్లగా ఉందా? :) మరియు దీన్ని చేయడం చాలా కష్టం కాదు! నేటి పాఠంలో, మేము RMI పరస్పర చర్య యొక్క అంశాలను విశ్లేషిస్తాము మరియు దానిని ఎలా కాన్ఫిగర్ చేయాలో కనుగొంటాము. మనకు అవసరమైన మొదటి విషయం క్లయింట్ మరియు సర్వర్. మేము నిజంగా కంప్యూటర్ పరిభాషలో లోతుగా డైవ్ చేయవలసిన అవసరం లేదు. RMI విషయానికి వస్తే, ఇవి కేవలం రెండు ప్రోగ్రామ్‌లు. వాటిలో ఒకటి ఒక వస్తువును కలిగి ఉంటుంది మరియు మరొకటి ఆ వస్తువుపై పద్ధతులను పిలుస్తుంది. వేరొక ప్రోగ్రామ్‌లో ఉన్న ఆబ్జెక్ట్‌కి కాల్ చేసే పద్ధతులు — ఇప్పుడు మనం ఇంకా చేయని పని! దీన్ని ప్రయత్నించడానికి ఇది సమయం! :) కూరుకుపోకుండా ఉండాలంటే, చేద్దాం' లు మా ప్రోగ్రామ్‌ను సరళంగా ఉంచుతాయి. సాధారణంగా, సర్వర్ క్లయింట్ కోరిన కొన్ని గణనలను నిర్వహిస్తుంది. మరియు అది మాతో ఉంటుంది. మా సర్వర్ సాధారణ కాలిక్యులేటర్ ప్రోగ్రామ్ అవుతుంది. ఇది ఒకే ఒక పద్ధతిని కలిగి ఉంటుంది:గుణించండి() . ఇది క్లయింట్ ప్రోగ్రామ్ ద్వారా దానికి పంపబడిన రెండు సంఖ్యలను గుణించి, ఆపై ఫలితాన్ని అందిస్తుంది. అన్నింటిలో మొదటిది, మనకు ఇంటర్ఫేస్ అవసరం:

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

public interface Calculator extends Remote {

   int multiply(int x, int y) throws RemoteException;
}
మనకు ఇంటర్ఫేస్ ఎందుకు అవసరం? ఎందుకంటే మీరు గత పాఠాలలో చదివిన ప్రాక్సీలను సృష్టించడంపై RMI ఆధారపడుతుంది . మీకు బహుశా గుర్తున్నట్లుగా, మేము ప్రాక్సీలతో ఇంటర్‌ఫేస్‌ల ద్వారా పని చేస్తాము, తరగతులు కాదు. మా ఇంటర్‌ఫేస్ కోసం 2 ముఖ్యమైన అవసరాలు ఉన్నాయి!
  1. ఇది తప్పనిసరిగా రిమోట్ ఇంటర్‌ఫేస్‌ను పొడిగించాలి.
  2. దాని అన్ని పద్ధతులు తప్పనిసరిగా రిమోట్‌ఎక్సెప్షన్‌ను విసరాలి (IDE దీన్ని స్వయంచాలకంగా చేయదు — మీరు దీన్ని మాన్యువల్‌గా జోడించాలి!).
ఇప్పుడు మనం మా కాలిక్యులేటర్ ఇంటర్‌ఫేస్‌ని అమలు చేసే సర్వర్ క్లాస్‌ని సృష్టించాలి . ఆచరణలో RMI - 2ఇక్కడ కూడా, ప్రతిదీ చాలా సులభం:

import java.rmi.RemoteException;

public class RemoteCalculationServer implements Calculator {

   @Override
   public int multiply(int x, int y) throws RemoteException {
       return x*y;
   }

}
ఇక్కడ వ్యాఖ్యానించడానికి నిజంగా ఏమీ లేదు :) ఇప్పుడు మనం మన కాలిక్యులేటర్ ఆబ్జెక్ట్‌ను కాన్ఫిగర్ చేసి రన్ చేసే సర్వర్ ప్రోగ్రామ్‌ను వ్రాయాలి. ఇది ఇలా కనిపిస్తుంది:

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

public class ServerMain {

   public static final String UNIQUE_BINDING_NAME = "server.calculator";

   public static void main(String[] args) throws RemoteException, AlreadyBoundException, InterruptedException {

       final RemoteCalculationServer server = new RemoteCalculationServer();

       final Registry registry = LocateRegistry.createRegistry(2732);

       Remote stub = UnicastRemoteObject.exportObject(server, 0);
       registry.bind(UNIQUE_BINDING_NAME, stub);

       Thread.sleep(Integer.MAX_VALUE);

   }
}
దీన్ని గుర్తించండి :) మొదటి పంక్తిలో, మేము కొన్ని స్ట్రింగ్ వేరియబుల్‌ని ప్రకటిస్తాము:

public static final String UNIQUE_BINDING_NAME = "server.calculator";
ఈ స్ట్రింగ్ రిమోట్ వస్తువు యొక్క ప్రత్యేక పేరు. మా సర్వర్‌ని కనుగొనడానికి మా క్లయింట్ ప్రోగ్రామ్ ఈ పేరును ఉపయోగిస్తుంది: మీరు దీన్ని తర్వాత చూస్తారు. తరువాత, మేము మా కాలిక్యులేటర్ వస్తువును సృష్టిస్తాము:

final RemoteCalculationServer server = new RemoteCalculationServer();
ఇక్కడ ప్రతిదీ స్పష్టంగా ఉంది. తదుపరిది మరింత ఆసక్తికరంగా ఉంటుంది:

final Registry registry = LocateRegistry.createRegistry(2732);
ఈ రిజిస్ట్రీ ఆబ్జెక్ట్ రిమోట్ ఆబ్జెక్ట్‌ల రిజిస్ట్రీ. ఇవి ఇతర ప్రోగ్రామ్‌లు రిమోట్‌గా యాక్సెస్ చేయగల వస్తువులు :) మేము 2732 నంబర్‌ను LocateRegistry.createRegistry() పద్ధతికి పంపాము. ఇది పోర్ట్ నంబర్ — ఇతర ప్రోగ్రామ్‌లు మా ఆబ్జెక్ట్ రిజిస్ట్రీని కనుగొనడానికి ఉపయోగించే ప్రత్యేక సంఖ్య (మళ్లీ, మీరు దీన్ని క్రింద చూస్తారు). కుడివైపు కదులుతూ... తదుపరి లైన్‌లో ఏమి జరుగుతుందో చూద్దాం:

Remote stub = UnicastRemoteObject.exportObject(server, 0);
మేము ఈ లైన్‌లో స్టబ్‌ని క్రియేట్ చేస్తాము. ఒక స్టబ్ మొత్తం రిమోట్ కాల్‌ను కలుపుతుంది. మీరు దీన్ని RMI యొక్క అతి ముఖ్యమైన అంశంగా పరిగణించవచ్చు. ఇది ఏమి చేస్తుంది?
  1. ఇది ఏదో ఒక పద్ధతి యొక్క రిమోట్ కాల్ గురించి మొత్తం సమాచారాన్ని అందుకుంటుంది.
  2. పద్ధతికి పారామితులు ఉంటే, స్టబ్ వాటిని డీరియలైజ్ చేస్తుంది. ఈ పాయింట్‌పై శ్రద్ధ వహించండి! మీరు రిమోట్‌గా పిలవబడే పద్ధతులకు పంపే వాదనలు తప్పనిసరిగా సీరియలైజ్ చేయబడాలి (అన్ని తరువాత, అవి నెట్‌వర్క్ ద్వారా ప్రసారం చేయబడతాయి). ఇది మాకు సమస్య కాదు — మేము కేవలం సంఖ్యలను ప్రసారం చేస్తున్నాము. కానీ మీరు వస్తువులను ప్రసారం చేస్తున్నట్లయితే, ఈ అవసరాన్ని మర్చిపోకండి!
  3. ఆ తరువాత, స్టబ్ కావలసిన పద్ధతిని పిలుస్తుంది.
మేము మా కాలిక్యులేటర్ సర్వర్ వస్తువును UnicastRemoteObject.exportObject() పద్ధతికి పంపుతాము. ఈ విధంగా మేము రిమోట్‌గా దాని పద్ధతులను కాల్ చేయడాన్ని సాధ్యం చేస్తాము. చేయవలసినది ఒక్కటే మిగిలి ఉంది:

registry.bind(UNIQUE_BINDING_NAME, stub);
మేము రిమోట్ ఆబ్జెక్ట్ రిజిస్ట్రీలో మా స్టబ్‌ను మేము ప్రారంభంలోనే రూపొందించిన పేరుతో "రిజిస్టర్" చేస్తాము. ఇప్పుడు క్లయింట్ దానిని కనుగొనగలరు! మేము ప్రోగ్రామ్ యొక్క ప్రధాన థ్రెడ్‌ను చివరిలో నిద్రపోయేలా ఉంచినట్లు మీరు గమనించి ఉండవచ్చు:

Thread.sleep(Integer.MAX_VALUE);
చాలా కాలం పాటు పనిచేయడానికి సర్వర్ అవసరం. IDEలో, మేము ఏకకాలంలో రెండు ప్రధాన() పద్ధతులను ప్రారంభిస్తాము: మొదటిది, సర్వర్ యొక్క ప్రధాన() పద్ధతి ( మేము ఇప్పటికే వ్రాసిన సర్వర్‌మెయిన్ క్లాస్‌లో), మరియు రెండవది, క్లయింట్ యొక్క ప్రధాన() పద్ధతి ( క్లైంట్‌మెయిన్ క్లాస్‌లో, మేము క్రింద వ్రాస్తాము). మేము క్లయింట్‌ను ప్రారంభించేటప్పుడు సర్వర్ ప్రోగ్రామ్ నిలిపివేయబడకపోవడం చాలా ముఖ్యం, కాబట్టి మేము దానిని ఎక్కువసేపు నిద్రపోనివ్వండి. ఏ సందర్భంలోనైనా, ఇది రన్ అవుతూనే ఉంటుంది :) ఇప్పుడు మనం మన సర్వర్ యొక్క ప్రధాన() పద్ధతిని అమలు చేయవచ్చు. దీన్ని అమలు చేయనివ్వండి మరియు క్లయింట్ ప్రోగ్రామ్ కొంత పద్ధతిని పిలవడానికి వేచి ఉండండి :) ఇప్పుడు క్లయింట్ ప్రోగ్రామ్‌ను వ్రాద్దాం! ఇది గుణకారం కోసం మా సర్వర్‌కు నంబర్‌లను పంపుతుంది.

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

public class ClientMain {

   public static final String UNIQUE_BINDING_NAME = "server.calculator";

   public static void main(String[] args) throws RemoteException, NotBoundException {

       final Registry registry = LocateRegistry.getRegistry(2732);

       Calculator calculator = (Calculator) registry.lookup(UNIQUE_BINDING_NAME);

       int multiplyResult = calculator.multiply(20, 30);

       System.out.println(multiplyResult);
   }
}
ఇది సరళంగా కనిపిస్తుంది. అయితే ఇక్కడ ఏం జరుగుతోంది? ముందుగా, క్లయింట్ తప్పనిసరిగా రిమోట్‌గా కాల్ చేసే ఆబ్జెక్ట్ యొక్క ప్రత్యేక పేరును తెలుసుకోవాలి. దీని ప్రకారం, క్లయింట్ ప్రోగ్రామ్‌లో, మేము పబ్లిక్ స్టాటిక్ ఫైనల్ స్ట్రింగ్ UNIQUE_BINDING_NAME = "server.calculator"ని సృష్టించాము; వేరియబుల్. తరువాత, ప్రధాన () పద్ధతిలో, మేము రిమోట్ వస్తువుల రిజిస్టర్‌కు ప్రాప్యతను పొందుతాము. దీన్ని చేయడానికి, మేము LocateRegistry.getRegistry() పద్ధతికి కాల్ చేయాలి మరియు సర్వర్‌మెయిన్ ప్రోగ్రామ్‌లో మా రిజిస్ట్రీని సృష్టించడానికి ఉపయోగించే పోర్ట్ నంబర్‌ను పాస్ చేయాలి (పోర్ట్ 2732; ఈ నంబర్ కేవలం ఒక ఉదాహరణ - మీరు వేరే నంబర్‌ని ఉపయోగించి ప్రయత్నించవచ్చు):

final Registry registry = LocateRegistry.getRegistry(2732);
ఇప్పుడు మనం రిజిస్ట్రీ నుండి కావలసిన వస్తువును పొందాలి! ఇది చాలా సులభం, ఎందుకంటే దాని ప్రత్యేక పేరు మాకు తెలుసు!

Calculator calculator = (Calculator) registry.lookup(UNIQUE_BINDING_NAME);
టైప్ కాస్టింగ్‌పై శ్రద్ధ వహించండి. మేము అందుకున్న ఆబ్జెక్ట్‌ను కాలిక్యులేటర్ ఇంటర్‌ఫేస్‌కి ప్రసారం చేసాము, రిమోట్ కాలిక్యులేషన్ సర్వర్ క్లాస్‌కి కాదు . మేము పాఠం ప్రారంభంలో చెప్పినట్లుగా, RMI ప్రాక్సీపై ఆధారపడుతుంది, కాబట్టి రిమోట్ కాల్‌లు ఇంటర్‌ఫేస్ పద్ధతులకు మాత్రమే అందుబాటులో ఉంటాయి, తరగతుల పద్ధతులకు కాదు. చివరగా, మన వస్తువుపై గుణకారం() పద్ధతిని రిమోట్‌గా పిలుస్తాము మరియు ఫలితాన్ని కన్సోల్‌కు అవుట్‌పుట్ చేస్తాము.

int multiplyResult = calculator.multiply(20, 30);
System.out.println(multiplyResult);
సర్వర్‌మెయిన్ క్లాస్ మెయిన్ () పద్ధతి ఇప్పటికే చాలా కాలంగా అమలవుతోంది. ఇప్పుడు క్లయింట్ ప్రోగ్రామ్‌లో ( ClientMain ) మెయిన్() పద్ధతిని అమలు చేయడానికి సమయం ఆసన్నమైంది ! కన్సోల్ అవుట్‌పుట్:

600
అంతే! మా ప్రోగ్రామ్ (రెండు ప్రోగ్రామ్‌లు, వాస్తవానికి!) అది ఏమి చేయాలో అది చేసింది :) మీకు సమయం మరియు కోరిక ఉంటే, మీరు దీన్ని కొద్దిగా మసాలా చేయవచ్చు. ఉదాహరణకు, కాలిక్యులేటర్ నాలుగు ప్రామాణిక అంకగణిత కార్యకలాపాలకు మద్దతు ఇచ్చేలా చేయండి మరియు సంఖ్యలను ఆదిమ రకాలుగా కాకుండా, CalculationInstance(int x, int y) ఆబ్జెక్ట్‌లుగా పాస్ చేయండి. తదుపరి పాఠంలో కలుద్దాం! :)
వ్యాఖ్యలు
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION