JavaRush /جاوا بلاگ /Random-UR /RMI: استعمال کی مشق

RMI: استعمال کی مشق

گروپ میں شائع ہوا۔
ہیلو! آج ہم ایک دلچسپ موضوع پر نظر ڈالیں گے - RMI ۔ اس کا مطلب ریموٹ میتھڈ انوکیشن ہے ۔ RMI: استعمال کی مشق - 1RMI کے ساتھ، آپ دو پروگراموں کو ایک دوسرے کے ساتھ بات چیت کرنا سکھا سکتے ہیں، چاہے وہ مختلف کمپیوٹرز پر ہوں۔ اچھا لگتا ہے؟ :) لیکن یہ کرنا اتنا مشکل نہیں ہے! آج کے لیکچر میں ہم سمجھیں گے کہ RMI تعامل کن حصوں پر مشتمل ہے اور اسے کیسے ترتیب دیا جائے۔ پہلی چیز جس کی ہمیں ضرورت ہے وہ ایک کلائنٹ اور سرور ہے ۔ آپ کو کمپیوٹر کی اصطلاحات میں زیادہ گہرائی میں جانے کی ضرورت نہیں ہے۔ RMI کے معاملے میں، یہ صرف دو پروگرام ہیں۔ ان میں سے ایک کسی چیز پر مشتمل ہوگا، اور دوسرا اس چیز کے طریقوں کو کال کرے گا۔ ایک پروگرام میں کسی چیز کے کال کرنے کے طریقے جو دوسرے پروگرام میں موجود ہیں - ہم نے پہلے کبھی ایسا نہیں کیا! اسے آزمانے کا وقت ہے! :) جنگل میں ڈوبنے کے لئے نہیں، ہمارے پروگرام کو آسان ہونے دیں۔ عام طور پر، سرورز عام طور پر کچھ ایسے حسابات انجام دیتے ہیں جو کلائنٹ کی درخواست کرتا ہے۔ ہمارے لیے بھی ایسا ہی ہوگا۔ ہمارے پاس سرور کے طور پر ایک سادہ کیلکولیٹر پروگرام ہوگا۔ اس کے پاس صرف ایک طریقہ ہوگا - multiply(). یہ کلائنٹ پروگرام کے ذریعے بھیجے گئے دو نمبروں کو ضرب دے گا اور نتیجہ واپس کر دے گا۔ سب سے پہلے ہمیں ایک انٹرفیس کی ضرورت ہے:
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 میں خود بخود نہیں ہوتا ہے، آپ کو اسے دستی طور پر لکھنا ہوگا!)
اب ہمیں ایک سرور کلاس بنانے کی ضرورت ہے جو ہمارے انٹرفیس کو نافذ کرے گی Calculator۔ 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);
ہمیں صرف سرور کو زیادہ دیر تک چلانے کی ضرورت ہے۔ ہم IDEa میں ایک ساتھ دو طریقے چلائیں گے main(): پہلا سرور ایک (کلاس میں جو ServerMainہم پہلے ہی لکھ چکے ہیں) اور پھر کلائنٹ ایک (کلاس میں 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);
   }
}
وہ غیر پیچیدہ لگ رہی ہے۔ یہاں کیا ہو رہا ہے؟ سب سے پہلے، کلائنٹ کو اس چیز کے منفرد نام سے آگاہ ہونا چاہیے جس کے طریقوں سے وہ دور سے کال کرے گا۔ اس لیے کلائنٹ پروگرام میں ہم نے ایک ویری ایبل بھی بنایا ہے۔اس public static final String UNIQUE_BINDING_NAME = "server.calculator"; کے بعد، طریقہ میں main()ہمیں ریموٹ آبجیکٹ کے رجسٹر تک رسائی حاصل ہوتی ہے۔ ایسا کرنے کے لیے، ہمیں طریقہ کو کال کرنا ہوگا LocateRegistry.getRegistry()اور وہاں پورٹ نمبر پاس کرنا ہوگا جس پر ہمارا رجسٹر سرور مین پروگرام میں بنایا گیا تھا - پورٹ 2732 (یہ نمبر مثال کے لیے منتخب کیا گیا تھا، آپ کوئی اور استعمال کرنے کی کوشش کر سکتے ہیں):
final Registry registry = LocateRegistry.getRegistry(2732);
اب ہمیں صرف رجسٹر سے مطلوبہ چیز حاصل کرنی ہے! یہ آسان ہے کیونکہ ہم اس کا منفرد نام جانتے ہیں!
Calculator calculator = (Calculator) registry.lookup(UNIQUE_BINDING_NAME);
ٹائپ کاسٹنگ پر توجہ دیں۔ ہم نتیجے میں آنے والی چیز کو کنکریٹ کلاس کے بجائے انٹرفیسCalculator RemoteCalculationServer پر ڈالتے ہیں ۔ جیسا کہ ہم نے لیکچر کے آغاز میں کہا، RMI پراکسی کے استعمال پر مبنی ہے، اس لیے ریموٹ کال صرف انٹرفیس کے طریقوں کے لیے دستیاب ہے، کلاسز کے لیے نہیں۔ آخر میں، ہم multiply()اپنے آبجیکٹ پر ایک طریقہ کو دور سے کال کرتے ہیں اور نتیجہ کو کنسول پر پرنٹ کرتے ہیں۔
int multiplyResult = calculator.multiply(20, 30);
System.out.println(multiplyResult);
ہم نے بہت پہلے main()کلاس میں طریقہ شروع کیا تھا، اب وقت آگیا ہے کہ کلائنٹ پروگرام میں اس طریقہ کو لانچ کیا جائے ! کنسول آؤٹ پٹ: 600 بس! ہمارے پروگرام (یہاں تک کہ دو!) نے کامیابی کے ساتھ اپنے فنکشن کو پورا کیا :) اگر آپ کے پاس وقت اور خواہش ہے تو آپ اسے تھوڑا سا متنوع بنا سکتے ہیں۔ مثال کے طور پر، اس بات کو یقینی بنائیں کہ کیلکولیٹر چاروں معیاری کارروائیوں کو سپورٹ کرتا ہے، نہ کہ نمبرز، بلکہ ایک شے کو پیرامیٹرز کے طور پر پاس کیا گیا ہے ۔ اضافی مواد کے طور پر، آپ مضامین اور مثالیں دیکھ سکتے ہیں - یہاں: ServerMainmain()ClientMainCalculationInstance(int x, int y) اگلی کلاسوں میں ملتے ہیں! :)
تبصرے
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION