JavaRush /Java блогу /Random-KY /RMI: колдонуу практикасы

RMI: колдонуу практикасы

Группада жарыяланган
Салам! Бүгүн биз абдан кызыктуу теманы карап чыгабыз - RMI . Бул Remote Method Invocation дегенди билдирет . RMI: колдонуу практикасы - 1RMI менен сиз эки программаны, алар башка компьютерлерде болсо да, бири-бири менен байланышууга үйрөтө аласыз. Сонун угулат? :) Бирок муну жасоо анчалык деле кыйын эмес! Бүгүнкү лекцияда RMI өз ара аракеттенүүсү кандай бөлүктөрдөн тураарын жана аны кантип конфигурациялоону түшүнөбүз. Бизге керек болгон биринчи нерсе - кардар жана server . Компьютердик терминологияга өтө терең кирүүнүн кереги жок. RMI учурда, бул жөн гана эки программа. Алардын бири кандайдыр бир an objectти камтыйт, ал эми экинчиси бул an objectтин ыкмаларын чакырат. Башка программада жайгашкан бир программадагы an objectтин ыкмаларын чакыруу - биз буга чейин мындай кылган эмеспиз! Аны сынап көрүүгө убакыт келди! :) Жапайы жерге чөгүп кетпеш үчүн программабыз жөнөкөй болсун. Жалпысынан алганда, serverлер адатта кардар сураган кандайдыр бир эсептөөлөрдү жүргүзүшөт. Биз үчүн да ошондой болот. Бизде server катары жөнөкөй калькулятор программасы болот. Анын бир гана ыкмасы болот - 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. Ал Remote token интерфейсин мурасташ керек.
  2. Анын бардык ыкмалары RemoteException ыргытышы керек (бул IDEде автоматтык түрдө жасалbyte, сиз аны кол менен жазышыңыз керек!).
Эми биз интерфейсибизди ишке ашыра турган server классын түзүшүбүз керек 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;
   }

}
Бул жерде комментарий бере турган деле көп нерсе жок :) Эми биз serverдик калькулятор классыбызды конфигурациялай турган жана ишке киргизе турган server программасын жазышыбыз керек. Ал мындай болот:
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";
Бул сап алыскы an objectтин уникалдуу аты . Бул ат менен кардар программасы биздин serverди таба алат: муну кийинчерээк көрөсүз. Андан кийин биз калькулятор an objectисин түзөбүз:
final RemoteCalculationServer server = new RemoteCalculationServer();
Бул жерде баары түшүнүктүү. Төмөнкүлөр кызыктуураак:
final Registry registry = LocateRegistry.createRegistry(2732);
Бул Реестр деп аталган нерсе жок кылынган an objectтердин реестри . "Жок кылынды" биз аларды компьютерден жок кылган деген мааниде эмес, бул реестрдеги an objectтерге башка программалардан алыстан кирүүгө боло тургандыгы үчүн :) LocateRegistry.createRegistry()Биз методго 2732 санын өткөрдүк.Бул порт номери. Эгерде сиз порт деген эмне экенин билбесеңиз, аны бул жерден окусаңыз болот , бирок азыр бул уникалдуу номер экенин эстен чыгарбоо керек, анын жардамы менен башка программалар биздин an object реестрибизди таба алышат (сиз муну төмөндө көрөсүз). Келгиле, уланталы. Келгиле, кийинки сапта эмне болорун карап көрөлү:
Remote stub = UnicastRemoteObject.exportObject(server, 0);
Бул сызыкта биз stub түзөбүз . Тасма алыскы чалуу процессин өзүнө камтыйт. Бул RMIнин эң маанилүү элементи деп айтууга болот . Ал эмне кылып жатат?
  1. Методго алыскы чалуу жөнүндө бардык маалыматты алат.
  2. Эгерде методдун параметрлери болсо, stub аларды сериядан чыгарат. Ушул пунктка көңүл буруңуз! Алыскы чалуулардын ыкмаларына өткөргөн параметрлериңиз сериялаштырылуучу болушу керек (анткени алар тармак аркылуу өткөрүлөт). Бизде андай көйгөй жок - биз сандарды гана өткөрүп жатабыз. Бирок, эгерде сиз an objectтерди өткөрүп берсеңиз, анда бул жөнүндө унутпаңыз!
  3. Андан кийин, ал каалаган ыкманы чакырат.
UnicastRemoteObject.exportObject()Биз serverдик калькулятор an objectисин методго өткөрүп беребиз . Ушундай жол менен биз анын ыкмаларын алыстан чакырууга мүмкүнчүлүк түзөбүз. Бизде бир гана иш калды:
registry.bind(UNIQUE_BINDING_NAME, stub);
Биз түптөөбүздү эң башында ойлоп тапкан атыбыз менен алыскы an objectтердин реестринде “каттаабыз”. Эми кардар аны таба алат! Сиз аягында программанын негизги жиптерин уктатканыбызды байкаган чыгарсыз:
Thread.sleep(Integer.MAX_VALUE);
Биз жөн гана serverди узак убакытка иштетишибиз керек. Биз IDEaда бир эле учурда эки ыкманы иштетебиз main(): адегенде server (биз буга чейин жазган класста ServerMain), андан кийин кардар (класста ClientMainбиз төмөндө жазабыз). Биз кардарды ишке киргизип жатканда serverдик программа иштебей калбашы маанилүү, ошондуктан биз аны жөн гана узак убакытка уктатып коёбуз. Бул дагы эле иштейт :) Эми биз main()serverдик ыкмабызды иштете алабыз. Аны иштетип, кардар программасы кандайдыр бир ыкманы чакырганча күтө туруңуз :) Эми кардар программасын жазалы! Ал көбөйүү үчүн биздин serverге сандарды жөнөтөт.
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);
   }
}
Ал жөнөкөй көрүнөт. Бул жерде эмне болуп жатат? Биринчиден, кардар методдору алыстан чакыра турган an objectинин уникалдуу аталышын бorши керек. Ошондуктан, кардар программасында биз да өзгөрмө түздүк.Андан public static final String UNIQUE_BINDING_NAME = "server.calculator"; кийин, методдо main()биз алыскы an objectтердин реестрине кирүү мүмкүнчүлүгүн алабыз. Бул үчүн, биз ыкманы чакырып LocateRegistry.getRegistry(), ал жерге ServerMain программасында реестрибиз түзүлгөн порт номерин өткөрүп беришибиз керек - 2732 порт (бул сан мисал үчүн тандалган, башкасын колдонуп көрүңүз):
final Registry registry = LocateRegistry.getRegistry(2732);
Эми биз каалаган an objectти реестрден алышыбыз керек! Бул оңой, анткени биз анын өзгөчө атын билебиз!
Calculator calculator = (Calculator) registry.lookup(UNIQUE_BINDING_NAME);
Типтин кастингине көңүл буруңуз. Биз пайда болгон an objectти конкреттүү класска эмес, интерфейскеCalculator RemoteCalculationServer чыгардык . Лекциянын башында айткандай, RMI проксиди колдонууга негизделген, ошондуктан аралыктан чалуу класстар үчүн эмес, интерфейстердин методдору үчүн гана жеткorктүү. Аягында биз multiply()an objectибиздеги методду алыстан чакырып, натыйжаны консолго басып чыгарабыз.
int multiplyResult = calculator.multiply(20, 30);
System.out.println(multiplyResult);
Биз методду main()класста көп убакыт мурун ишке киргизгенбиз, бул ыкманы кардар программасында ServerMainишке киргизүүгө убакыт келди ! Консолдун чыгышы: 600 Мына ушундай! Биздин программа (экөө да!) өз функциясын ийгorктүү аткарды :) Эгер убакыт жана каалоо болсо, аны бир аз диверсификациялай аласыз. Мисалы, калькулятор бардык төрт стандарттуу операцияны колдой тургандыгын, сандарды эмес, an object параметр катары өткөрүлүп берилгенин текшериңиз . Кошумча материал катары, сиз макалаларды жана мисалдарды карай аласыз - бул жерде: main()ClientMainCalculationInstance(int x, int y) Кийинки сабактарда көрүшкөнчө! :)
Комментарийлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION