📜 ⬆️ ⬇️

RMI (Remote Method Invocation)

It so happened that the task required the use of a remote method call. Having rummaged on Habré, found nothing on the matter (it would be desirable to esteem something as the first acquaintance, before reading the documentation). Having studied the specifications on java.sun.com, I hasten to share with you my first article. :)

"What is RMI?"


Remote method Invocation - a mechanism that allows you to call the method of a remote object. According to him, all operations on the preparation and transmission of data are encapsulated in the called method of the stub client object. The method call itself is no different from the method call of a regular local object, with a few exceptions:
It should also be noted that when calling the method we work with the remote interface, and not with the remote class.

“Why is this needed?”


The task of RMI is the organization of client-server interaction. This means that you do not have to worry about transferring and preprocessing data (protocol, etc.). Conveniently? Yes. But not in all cases. If in your client-server environment the work of programs written not only in java is implied, RMI is of little use (although with a strong desire you can try to get out with JNI).
')

"Let's write something already!"


Let's. Consider the example of distributed computing. Our task is this: we will search for simple numbers in the simplest way, by searching. Distributed, we will check the numbers by selecting the divisors from 2 to sqrt (n), where n is the number we are checking. (“Distributed computing” is a loud name for such an example. But after all, we calculate? Yes! Distributed? Distributed!)

We will solve the problem this way: there is a server that will “feed” numbers for verification to “registered” clients, therefore we will interact in both directions (client-> server - registration, server-> client - number for verification), for this we will describe 2 interface:
public interface ClientRegister extends Remote { public void register (PrimeChecker checker) throws RemoteException; } public interface PrimeChecker extends Remote { public boolean check (BigDecimal number) throws RemoteException; } * This source code was highlighted with Source Code Highlighter .
  1. public interface ClientRegister extends Remote { public void register (PrimeChecker checker) throws RemoteException; } public interface PrimeChecker extends Remote { public boolean check (BigDecimal number) throws RemoteException; } * This source code was highlighted with Source Code Highlighter .
  2. public interface ClientRegister extends Remote { public void register (PrimeChecker checker) throws RemoteException; } public interface PrimeChecker extends Remote { public boolean check (BigDecimal number) throws RemoteException; } * This source code was highlighted with Source Code Highlighter .
  3. public interface ClientRegister extends Remote { public void register (PrimeChecker checker) throws RemoteException; } public interface PrimeChecker extends Remote { public boolean check (BigDecimal number) throws RemoteException; } * This source code was highlighted with Source Code Highlighter .
  4. public interface ClientRegister extends Remote { public void register (PrimeChecker checker) throws RemoteException; } public interface PrimeChecker extends Remote { public boolean check (BigDecimal number) throws RemoteException; } * This source code was highlighted with Source Code Highlighter .
  5. public interface ClientRegister extends Remote { public void register (PrimeChecker checker) throws RemoteException; } public interface PrimeChecker extends Remote { public boolean check (BigDecimal number) throws RemoteException; } * This source code was highlighted with Source Code Highlighter .
  6. public interface ClientRegister extends Remote { public void register (PrimeChecker checker) throws RemoteException; } public interface PrimeChecker extends Remote { public boolean check (BigDecimal number) throws RemoteException; } * This source code was highlighted with Source Code Highlighter .
public interface ClientRegister extends Remote { public void register (PrimeChecker checker) throws RemoteException; } public interface PrimeChecker extends Remote { public boolean check (BigDecimal number) throws RemoteException; } * This source code was highlighted with Source Code Highlighter .

The ClientRegister interface is used by the client to register itself on the server as PrimeChecker`a. The server uses PrimeChecker to pass the number to the client for verification.

As you have noticed, the remote interface must extend, directly or indirectly, the Remote interface. Also among other exceptions we will define RemoteException (we spoke about it above).

Let's start the server implementation ( full code ):
  1. public class PrimeNumbersSearchServer implements ClientRegister {
  2. ...
  3. public static void main ( String [] args) {
  4. PrimeNumbersSearchServer server = new PrimeNumbersSearchServer ();
  5. try {
  6. ClientRegister stub = (ClientRegister) UnicastRemoteObject.exportObject (server, 0);
  7. Registry registry = LocateRegistry.createRegistry (12345);
  8. registry.bind ( "ClientRegister" , stub);
  9. server.startSearch ();
  10. } catch (Exception e) {
  11. System. out .println ( "Error occured:" + e.getMessage ());
  12. System.exit (1);
  13. }
  14. }
  15. }
* This source code was highlighted with Source Code Highlighter .

Let's sort the initialization:
  1. ClientRegister stub = (ClientRegister) UnicastRemoteObject.exportObject (server, 0);
* This source code was highlighted with Source Code Highlighter .

We export the remote object and get a stub, through which the client will call the methods of our object. The second parameter, exportObject, is the port that will be used to connect to the remote object, 0 is the choice of any free port. stub must be passed to the client. There are completely different options. You can even transfer the stub to the client on a 3.5 '' diskette :) We will use the RMI registrar. It can either be created inside our vm, or used as “external”, represented by the rmiregistry utility. I used the first option:
  1. Registry registry = LocateRegistry.createRegistry (12345);
  2. registry.bind ( "ClientRegister" , stub);
* This source code was highlighted with Source Code Highlighter .

Create a logger and associate our stub with the name ClientRegister. The registrar will accept connections on port 12345.

Now the client ( full code ):
  1. public class PrimeNumbersSearchClient implements PrimeChecker {
  2. ...
  3. public static void main ( String [] args) {
  4. PrimeNumbersSearchClient client = new PrimeNumbersSearchClient ();
  5. try {
  6. Registry registry = LocateRegistry.getRegistry ( null , 12345);
  7. ClientRegister server = (ClientRegister) registry.lookup ( "ClientRegister" );
  8. PrimeChecker stub = (PrimeChecker) UnicastRemoteObject.exportObject (client, 0);
  9. server.register (stub);
  10. } catch (Exception e) {
  11. System. out .println ( "Error occured:" + e.getMessage ());
  12. System.exit (1);
  13. }
  14. }
  15. }
* This source code was highlighted with Source Code Highlighter .

The client needs to get a server stub to register.
  1. Registry registry = LocateRegistry.getRegistry ( null , 12345);
  2. ClientRegister server = (ClientRegister) registry.lookup ( "ClientRegister" );
* This source code was highlighted with Source Code Highlighter .

We find the remote recorder and request a stub associated with it with the name “ClientRegister”. The first parameter LocateRegistry.getRegistry (null, 12345) is the host (null - localhost), the second is the port.

Next, export the client remote object and transfer the stub server (already client) to the server - register. The server will add the client to the queue of available checkers and start sending numbers to it for verification. After checking, if it is completed without errors, the client enters the queue again, etc.

UPD: moved to Java

Source: https://habr.com/ru/post/74639/


All Articles