JavaRush /وبلاگ جاوا /Random-FA /RMI: تمرین استفاده

RMI: تمرین استفاده

در گروه منتشر شد
سلام! امروز ما به یک موضوع نسبتاً جالب نگاه خواهیم کرد - RMI . این مخفف Remote Method Invocation است . RMI: تمرین استفاده - 1با RMI می توانید دو برنامه را آموزش دهید که با یکدیگر ارتباط برقرار کنند، حتی اگر در رایانه های مختلف باشند. باحال به نظر می رسد؟ :) اما انجام آن چندان دشوار نیست! در سخنرانی امروز خواهیم فهمید که تعامل 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);
این چیزی که Registry نام دارد، رجیستری از اشیاء حذف شده است . "حذف شده" نه به این معنا که آنها را از رایانه حذف کرده ایم، بلکه به این معناست که اشیاء این رجیستر از راه دور از برنامه های دیگر قابل دسترسی هستند :) LocateRegistry.createRegistry()ما عدد 2732 را به روش ارسال کردیم. این شماره پورت است. اگر نمی‌دانید پورت چیست، می‌توانید آن را در اینجا بخوانید ، اما در حال حاضر فقط باید به خاطر داشته باشید که این یک شماره منحصربه‌فرد است که توسط آن سایر برنامه‌ها می‌توانند رجیستری شی ما را پیدا کنند (این را نیز در زیر مشاهده خواهید کرد). بیایید ادامه دهیم. بیایید ببینیم در خط بعدی چه اتفاقی می افتد:
Remote stub = UnicastRemoteObject.exportObject(server, 0);
در این خط یک خرد ایجاد می کنیم . یک خرد کل فرآیند تماس از راه دور را در خود محصور می کند. می توان گفت که این مهمترین عنصر RMI است. او چه کار می کند؟
  1. تمام اطلاعات مربوط به تماس از راه دور با یک روش را دریافت می کند.
  2. اگر متد دارای پارامترهایی باشد، stub آنها را از فهرست خارج می کند. به این نکته توجه کنید! پارامترهایی که به روش‌های تماس‌های راه دور منتقل می‌کنید باید سریال‌سازی شوند (در نهایت، آنها از طریق شبکه منتقل می‌شوند). ما چنین مشکلی نداریم - ما فقط اعداد را منتقل می کنیم. اما اگر اشیاء را منتقل می کنید، آن را فراموش نکنید!
  3. پس از آن متد مورد نظر را فراخوانی می کند.
ما UnicastRemoteObject.exportObject()شیء ماشین حساب سرور خود را به متد ارسال می کنیم. به این ترتیب امکان فراخوانی روش های آن را از راه دور فراهم می کنیم. فقط یک کار داریم که باید انجام دهیم:
registry.bind(UNIQUE_BINDING_NAME, stub);
ما خرد خود را در رجیستری اشیاء راه دور با نامی که در همان ابتدا با آن آشنا شدیم، ثبت می کنیم. اکنون مشتری می تواند آن را پیدا کند! شاید متوجه شده باشید که در پایان موضوع اصلی برنامه را به حالت Sleep قرار می دهیم:
Thread.sleep(Integer.MAX_VALUE);
فقط باید سرور را برای مدت طولانی در حال اجرا نگه داریم. ما دو روش را همزمان در IDEa اجرا خواهیم کرد main(): ابتدا سرور یک (در کلاسی که ServerMainقبلاً نوشته ایم) و سپس یک مشتری (در کلاسی که ClientMainدر زیر خواهیم نوشت). مهم است که برنامه سرور در حین راه‌اندازی کلاینت از کار نرود، بنابراین به سادگی آن را برای مدت طولانی در حالت Sleep قرار می‌دهیم. همچنان کار خواهد کرد :) حالا می توانیم 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()و شماره پورتی را که رجیستر ما بر روی آن در برنامه ServerMain ایجاد شده است - پورت 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