JavaRush /בלוג Java /Random-HE /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);
הדבר הזה שנקרא רישום הוא רישום של אובייקטים שנמחקו . "נמחקו" לא במובן שמחקנו אותם מהמחשב, אלא בעובדה שניתן לגשת לאובייקטים מהאוגר הזה מרחוק מתוכנות אחרות :) 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()ולהעביר לשם את מספר היציאה שעליו נוצר הרישום שלנו בתוכנית ServerMain - יציאה 2732 (מספר זה נבחר לדוגמא, אתה יכול לנסות להשתמש באחד אחר):
final Registry registry = LocateRegistry.getRegistry(2732);
כעת כל שעלינו לעשות הוא לקבל את החפץ הרצוי מהפנקס! זה קל כי אנחנו מכירים את שמו הייחודי!
Calculator calculator = (Calculator) registry.lookup(UNIQUE_BINDING_NAME);
שימו לב לסוג הליהוק. אנו משליכים את האובייקט המתקבל לממשק Calculatorולא למחלקה קונקרטית RemoteCalculationServer . כפי שאמרנו בתחילת ההרצאה, RMI מבוסס על שימוש ב-proxy, ולכן קריאה מרחוק זמינה רק לשיטות של ממשקים, לא לשיעורים. בסוף, אנו קוראים מרחוק למתודה multiply()על האובייקט שלנו ומדפיסים את התוצאה לקונסולה.
int multiplyResult = calculator.multiply(20, 30);
System.out.println(multiplyResult);
השקנו את השיטה main()בכיתה ServerMainמזמן, הגיע הזמן להשיק את השיטה main()בתוכנית הלקוח ClientMain! תפוקת קונסולה: 600 זהו זה! התכנית שלנו (אפילו שתיים!) מילאה את תפקידה בהצלחה :) אם יש לכם זמן ורצון, תוכלו לגוון אותה מעט. לדוגמה, ודא שהמחשבון תומך בכל ארבע הפעולות הסטנדרטיות, ולא במספרים, אלא אובייקט מועבר כפרמטרים CalculationInstance(int x, int y). כחומר נוסף, אתה יכול להסתכל על מאמרים ודוגמאות - כאן: נתראה בשיעורים הבאים! :)
הערות
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION