John Squirrels
पातळी 41
San Francisco

जावा RMI

यादृच्छिक या ग्रुपमध्ये प्रकाशित केले
हाय! आज आपण एका ऐवजी मनोरंजक विषयावर विचार करू: Java 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. त्याच्या सर्व पद्धतींमध्ये RemoteException टाकणे आवश्यक आहे (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);
हे रेजिस्ट्री ऑब्जेक्ट रिमोट ऑब्जेक्ट्सची नोंदणी आहे. हे असे ऑब्जेक्ट्स आहेत ज्यात इतर प्रोग्राम्स दूरस्थपणे प्रवेश करू शकतात :) आम्ही LocateRegistry.createRegistry() पद्धतीवर 2732 क्रमांक पास केला आहे . हा पोर्ट क्रमांक आहे — एक अद्वितीय क्रमांक जो इतर प्रोग्राम आमची ऑब्जेक्ट रेजिस्ट्री शोधण्यासाठी वापरतील (पुन्हा, तुम्हाला हे खाली दिसेल). बरोबर पुढे जात आहोत... पुढच्या ओळीत काय होते ते पाहूया:

Remote stub = UnicastRemoteObject.exportObject(server, 0);
आम्ही या ओळीत एक स्टब तयार करतो. एक स्टब संपूर्ण रिमोट कॉल एन्कॅप्स्युलेट करतो. तुम्ही हा RMI चा सर्वात महत्वाचा घटक मानू शकता. ते काय करते?
  1. ते कोणत्या तरी पद्धतीच्या रिमोट कॉलबद्दल सर्व माहिती प्राप्त करते.
  2. पद्धतीमध्ये पॅरामीटर्स असल्यास, स्टब त्यांना डीसीरियलाइज करेल. या बिंदूकडे लक्ष द्या! तुम्ही रिमोटली कॉल केलेल्या पद्धतींवर पास करता ते वितर्क अनुक्रमे करण्यायोग्य असले पाहिजेत (शेवटी, ते नेटवर्कवर प्रसारित केले जातील). आमच्यासाठी ही समस्या नाही - आम्ही फक्त संख्या प्रसारित करत आहोत. परंतु आपण वस्तू प्रसारित करत असल्यास, ही आवश्यकता विसरू नका!
  3. त्यानंतर, स्टब इच्छित पद्धत कॉल करतो.
आम्ही आमचा कॅल्क्युलेटर सर्व्हर ऑब्जेक्ट UnicastRemoteObject.exportObject() पद्धतीने पास करतो. अशा प्रकारे आम्ही त्याच्या पद्धतींना दूरस्थपणे कॉल करणे शक्य करतो. फक्त एक गोष्ट करायची बाकी आहे:

registry.bind(UNIQUE_BINDING_NAME, stub);
रिमोट ऑब्जेक्ट रेजिस्ट्रीमध्ये आम्ही आमच्या स्टबची "नोंदणी" करतो ज्या नावाने आम्ही अगदी सुरुवातीला बनवले होते. आता क्लायंट शोधण्यास सक्षम असेल! कदाचित तुमच्या लक्षात आले असेल की आम्ही प्रोग्रामचा मुख्य धागा शेवटी झोपायला ठेवला आहे:

Thread.sleep(Integer.MAX_VALUE);
आम्हाला बर्याच काळासाठी सर्व्हरची आवश्यकता आहे. IDE मध्ये, आम्ही एकाच वेळी दोन मुख्य() पद्धती लाँच करू: पहिली, सर्व्हरची main() पद्धत ( सर्व्हरमेन क्लासमध्ये, जी आम्ही आधीच लिहिली आहे), आणि दुसरी, क्लायंटची main() पद्धत (ClientMain क्लासमध्ये , जे आम्ही खाली लिहू). हे महत्वाचे आहे की आम्ही क्लायंट सुरू करत असताना सर्व्हर प्रोग्राम संपुष्टात येत नाही, म्हणून आम्ही तो बराच वेळ झोपतो. कोणत्याही परिस्थितीत, ते चालूच राहील :) आता आपण आमच्या सर्व्हरची main() पद्धत चालवू शकतो. ते चालू द्या आणि क्लायंट प्रोग्रामची काही पद्धत कॉल होण्याची प्रतीक्षा करा :) आता क्लायंट प्रोग्राम लिहूया! ते गुणाकारासाठी आमच्या सर्व्हरला संख्या पाठवेल.

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" तयार केली; चल पुढे, main() पद्धतीमध्ये, आम्हाला रिमोट ऑब्जेक्ट्सच्या रजिस्टरमध्ये प्रवेश मिळतो. हे करण्यासाठी, आम्हाला LocateRegistry.getRegistry() पद्धतीवर कॉल करणे आवश्यक आहे आणि सर्व्हरमेन प्रोग्राममध्ये आमची रजिस्ट्री तयार करण्यासाठी वापरलेला पोर्ट नंबर पास करणे आवश्यक आहे (पोर्ट 2732; हा नंबर फक्त एक उदाहरण आहे — तुम्ही वेगळा नंबर वापरून पाहू शकता):

final Registry registry = LocateRegistry.getRegistry(2732);
आता आपल्याला फक्त रेजिस्ट्रीमधून इच्छित ऑब्जेक्ट मिळवण्याची आवश्यकता आहे! हे सोपे आहे, कारण आम्हाला त्याचे अद्वितीय नाव माहित आहे!

Calculator calculator = (Calculator) registry.lookup(UNIQUE_BINDING_NAME);
टाइप कास्टिंगकडे लक्ष द्या. आम्ही प्राप्त केलेला ऑब्जेक्ट कॅल्क्युलेटर इंटरफेसवर कास्ट करतो, रिमोट कॅल्क्युलेशन सर्व्हर वर्गावर नाही . आम्ही धड्याच्या सुरुवातीला म्हटल्याप्रमाणे, RMI प्रॉक्सीवर अवलंबून असते, त्यामुळे रिमोट कॉल्स केवळ इंटरफेसच्या पद्धतींसाठी उपलब्ध आहेत, वर्गांच्या पद्धतींसाठी नाही. शेवटी, आम्ही आमच्या ऑब्जेक्टवर multiply() पद्धतीला दूरस्थपणे कॉल करतो आणि परिणाम कन्सोलमध्ये आउटपुट करतो.

int multiplyResult = calculator.multiply(20, 30);
System.out.println(multiplyResult);
सर्व्हरमेन क्लासची main ( ) पद्धत आधीपासूनच बर्याच काळापासून चालू आहे. आता क्लायंट प्रोग्राम ( ClientMain ) मध्ये main() पद्धत चालवण्याची वेळ आली आहे ! कन्सोल आउटपुट:

600
बस एवढेच! आमच्या कार्यक्रमाने (दोन कार्यक्रम, प्रत्यक्षात!) जे करायला हवे होते ते केले :) जर तुमच्याकडे वेळ आणि इच्छा असेल तर तुम्ही याला थोडा मसाला देऊ शकता. उदाहरणार्थ, कॅल्क्युलेटरला चार मानक अंकगणितीय ऑपरेशन्सचे समर्थन करा आणि संख्यांना आदिम प्रकार म्हणून नाही, तर CalculationInstance(int x, int y) ऑब्जेक्ट्स म्हणून पास करा. पुढील धड्यात भेटू! :)
टिप्पण्या
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION