是否可以在两个类之间使用双向 RMI?

发布于 2024-07-22 05:40:54 字数 205 浏览 8 评论 0原文

我想在两个类(A 和 B)之间共享一些信息,这两个类在不同的 java 程序中运行。 我不想编写整个通信协议,而是想使用 java 内置 rmi 类来实现此目的。 目前,B 类能够远程运行属于 A 类的方法。 是否可以在 A 类中使用相同的“连接”来调用 B 类的方法? 否则我可能必须实现第二个 rmi 服务......

BR,

Markus

I want to share some information between two classes (A and B), which are running in different java programs. Instead of writing a whole communication protocol I want to use the java build-in rmi classes for that purpose. Currently class B is able to run a method which belongs to class A remotely. Is it somehow possible to use the same "connection" within class A to call a method of class B? Otherwise I probably have to implement a second rmi service ...

BR,

Markus

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

冷夜 2024-07-29 05:40:55

如果 B 实现 Remote,则可以将其导出并作为 RMI 调用中的参数传递给 A。 在这种情况下,无需在 RMI 注册表中注册 B,因为客户端将显式传递对其的引用。

If B implements Remote, it can be export and passed as a parameter in an RMI call to A. In this scenario, there's no need to register B in an RMI registry, since the client is being passed a reference to it explicitly.

薄暮涼年 2024-07-29 05:40:55

我在 cleint 和服务器之间实现了 2 路 RMI,服务器使用注册表公开其存根

  1. 客户端获取服务器的存根
  2. 然后客户端将其存根作为观察者放置到服务器的 addObserver 方法
  3. 服务器使用此存根通知客户端

以下代码将给出一个更好的主意

import java.rmi.*;
import java.rmi.registry.*;
import java.rmi.server.*;
import java.util.Observable;
import java.util.Observer;
import java.net.*;

import javax.rmi.ssl.SslRMIClientSocketFactory;
import javax.rmi.ssl.SslRMIServerSocketFactory;

interface ReceiveMessageInterface extends Remote
{
    /**
     * @param x
     * @throws RemoteException
     */
    void receiveMessage(String x) throws RemoteException;

    /**
     * @param observer
     * @throws RemoteException
     */
    void addObserver(Remote observer) throws RemoteException;
}

/**
 * 
 */
class RmiClient extends UnicastRemoteObject
{
    /**
     * @param args
     */
    static public void main(String args[])
    {
        ReceiveMessageInterface rmiServer;
        Registry registry;
        String serverAddress = args[0];
        String serverPort = args[1];
        String text = args[2];
        System.out.println("sending " + text + " to " + serverAddress + ":" + serverPort);
        try
        { // Get the server's stub
            registry = LocateRegistry.getRegistry(serverAddress, (new Integer(serverPort)).intValue());
            rmiServer = (ReceiveMessageInterface) (registry.lookup("rmiServer"));

            // RMI client will give a stub of itself to the server
            Remote aRemoteObj = (Remote) UnicastRemoteObject.exportObject(new RmiClient(), 0);
            rmiServer.addObserver(aRemoteObj);

            // call the remote method
            rmiServer.receiveMessage(text);
            // update method will be notified
        }
        catch (RemoteException e)
        {
            e.printStackTrace();
        }
        catch (NotBoundException e)
        {
            System.err.println(e);
        }
    }

    public void update(String a) throws RemoteException
    {
        // update should take some serializable object as param NOT Observable
        // and Object
        // Server callsbacks here
    }
}

/**
 * 
 */
class RmiServer extends Observable implements ReceiveMessageInterface
{
    String address;
    Registry registry;

    /**
     * {@inheritDoc}
     */
    public void receiveMessage(String x) throws RemoteException
    {
        System.out.println(x);
        setChanged();
        notifyObservers(x + "invoked me");
    }

    /**
     * {@inheritDoc}
     */
    public void addObserver(final Remote observer) throws RemoteException
    {
        // This is where you plug in client's stub
        super.addObserver(new Observer()
        {
            @Override
            public void update(Observable o,
                Object arg)
            {
                try
                {
                    ((RmiClient) observer).update((String) arg);
                }
                catch (RemoteException e)
                {

                }
            }
        });
    }

    /**
     * @throws RemoteException
     */
    public RmiServer() throws RemoteException
    {
        try
        {
            address = (InetAddress.getLocalHost()).toString();
        }
        catch (Exception e)
        {
            System.out.println("can't get inet address.");
        }
        int port = 3232;
        System.out.println("this address=" + address + ",port=" + port);
        try
        {
            registry = LocateRegistry.createRegistry(port);
            registry.rebind("rmiServer", this);
        }
        catch (RemoteException e)
        {
            System.out.println("remote exception" + e);
        }
    }

    /**
     * 
     * @param args
     */
    static public void main(String args[])
    {
        try
        {
            RmiServer server = new RmiServer();
        }
        catch (Exception e)
        {
            e.printStackTrace();
            System.exit(1);
        }
    }
}

I implemented 2 way RMI between cleint and server with server exposing its stub using Registry

  1. The client gets a stub of the server
  2. Then the client puts its stub as Observer to the server's addObserver method
  3. The server notifies the clients using this stub

The following code will gives a better idea

import java.rmi.*;
import java.rmi.registry.*;
import java.rmi.server.*;
import java.util.Observable;
import java.util.Observer;
import java.net.*;

import javax.rmi.ssl.SslRMIClientSocketFactory;
import javax.rmi.ssl.SslRMIServerSocketFactory;

interface ReceiveMessageInterface extends Remote
{
    /**
     * @param x
     * @throws RemoteException
     */
    void receiveMessage(String x) throws RemoteException;

    /**
     * @param observer
     * @throws RemoteException
     */
    void addObserver(Remote observer) throws RemoteException;
}

/**
 * 
 */
class RmiClient extends UnicastRemoteObject
{
    /**
     * @param args
     */
    static public void main(String args[])
    {
        ReceiveMessageInterface rmiServer;
        Registry registry;
        String serverAddress = args[0];
        String serverPort = args[1];
        String text = args[2];
        System.out.println("sending " + text + " to " + serverAddress + ":" + serverPort);
        try
        { // Get the server's stub
            registry = LocateRegistry.getRegistry(serverAddress, (new Integer(serverPort)).intValue());
            rmiServer = (ReceiveMessageInterface) (registry.lookup("rmiServer"));

            // RMI client will give a stub of itself to the server
            Remote aRemoteObj = (Remote) UnicastRemoteObject.exportObject(new RmiClient(), 0);
            rmiServer.addObserver(aRemoteObj);

            // call the remote method
            rmiServer.receiveMessage(text);
            // update method will be notified
        }
        catch (RemoteException e)
        {
            e.printStackTrace();
        }
        catch (NotBoundException e)
        {
            System.err.println(e);
        }
    }

    public void update(String a) throws RemoteException
    {
        // update should take some serializable object as param NOT Observable
        // and Object
        // Server callsbacks here
    }
}

/**
 * 
 */
class RmiServer extends Observable implements ReceiveMessageInterface
{
    String address;
    Registry registry;

    /**
     * {@inheritDoc}
     */
    public void receiveMessage(String x) throws RemoteException
    {
        System.out.println(x);
        setChanged();
        notifyObservers(x + "invoked me");
    }

    /**
     * {@inheritDoc}
     */
    public void addObserver(final Remote observer) throws RemoteException
    {
        // This is where you plug in client's stub
        super.addObserver(new Observer()
        {
            @Override
            public void update(Observable o,
                Object arg)
            {
                try
                {
                    ((RmiClient) observer).update((String) arg);
                }
                catch (RemoteException e)
                {

                }
            }
        });
    }

    /**
     * @throws RemoteException
     */
    public RmiServer() throws RemoteException
    {
        try
        {
            address = (InetAddress.getLocalHost()).toString();
        }
        catch (Exception e)
        {
            System.out.println("can't get inet address.");
        }
        int port = 3232;
        System.out.println("this address=" + address + ",port=" + port);
        try
        {
            registry = LocateRegistry.createRegistry(port);
            registry.rebind("rmiServer", this);
        }
        catch (RemoteException e)
        {
            System.out.println("remote exception" + e);
        }
    }

    /**
     * 
     * @param args
     */
    static public void main(String args[])
    {
        try
        {
            RmiServer server = new RmiServer();
        }
        catch (Exception e)
        {
            e.printStackTrace();
            System.exit(1);
        }
    }
}
魔法少女 2024-07-29 05:40:55

我已经有一段时间没有使用 RMI 了,但是 IIRC 如果类 B 实现 java.rmi.Remote 并将对其自身实例的引用作为参数传递给类 A 中的方法,则类A 应该接收一个存根,并且调用它的方法将在原始实例上调用。

然而,如果您有大量这样的 RMI 调用来回,您可能会遇到性能问题。

It's been a while since I've used RMI, but IIRC if class B implements java.rmi.Remote and passes a reference to an instance of itself as a parameter to the method in class A, then class A should receive a stub and methods called on it will be called on the original instance.

However, if you have a lot of such RMI calls going back anf fro, you will probably encounter performance problems.

醉生梦死 2024-07-29 05:40:55

如果您将 B 作为参数传递给 A 中的方法,然后使用该引用调用 B 上的方法,我相当确定反向连接已建立,并且我相当确定 RMI 注册表是为 B 所在的 JVM 创建的。 在某些时候,这给我们带来了一些特别严格的防火墙规则的麻烦。 我们的代码看起来有点像

Web服务器

public int uploadFile(FileItem fileItem){
    return ApplicationClassLoader
        .get(DocumentManager.class)
        .attachFile(new RemoteInputStreamImpl(fileItem.getInputStream());
    )
}

应用程序服务器

public int attachFile(RemoteInputStream in){
    ...

    byte[] buffer;
    while((buffer = in.read(1024)) != null) // Would return null to indicate EOF
      // Do some stuff

    return documentId;       
}

If you pass B as an argument to a method in A and then use that reference to call a method on B I am fairly certain that a reverse connection is established, and I am fairly certain that RMI Registry is created for the JVM where B resides. At some point this got us into a bit of trouble with particularly strict firewall rules. Our code looked a little something like

Web Server

public int uploadFile(FileItem fileItem){
    return ApplicationClassLoader
        .get(DocumentManager.class)
        .attachFile(new RemoteInputStreamImpl(fileItem.getInputStream());
    )
}

Application Server

public int attachFile(RemoteInputStream in){
    ...

    byte[] buffer;
    while((buffer = in.read(1024)) != null) // Would return null to indicate EOF
      // Do some stuff

    return documentId;       
}
指尖上的星空 2024-07-29 05:40:55

两个 JVM 都需要实现 RMI 服务。 但查看 java.rmi 中的各个类确实非常容易。

您不能做的是以某种方式使用一个 RMI 连接并进行双向通信。

Both JVMs would need to implement RMI services. But that is really very easy look at the various classes in java.rmi.

What you can't do is somehow use one RMI connection and do two way communication.

[旋木] 2024-07-29 05:40:55

某些 RMI 服务支持回调或侦听器,允许服务器通过同一连接异步调用客户端。 (抱歉,我不记得执行此操作的开放库的名称,快速谷歌并不是很有帮助)
标准 RMI 不支持这一点,相反您还需要将客户端公开为 RMI 服务。

Some RMI service support callbacks or listeners which allow the server to asynchronous call the client down the same connection. (Sorry I don't remember the name of the open libraries which do this, a quick google wasn't very helpful)
Standard RMI doesn't support this, instead you need to expose the client as an RMI service as well.

痕至 2024-07-29 05:40:55

RMI 双向:

服务器:

import java.io.IOException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.util.logging.Level;
import java.util.logging.Logger;

public class RMISERVER {

   public RMISERVER() throws IOException {

       Thread t;
        try {
            t = new Prou_run();
            t.start();
        } catch (RemoteException ex) {
            Logger.getLogger(RMISERVER.class.getName()).log(Level.SEVERE, null, ex);
        }

   }


   public static void main(String args[]) throws IOException {
     new RMISERVER();
   }
}


import java.io.File;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.rmi.Naming;
import java.rmi.Remote;
import java.rmi.registry.Registry;
import java.rmi.server.RMIClientSocketFactory;
import java.rmi.server.RMIServerSocketFactory;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.tree.DefaultMutableTreeNode;

//extends java.rmi.server.UnicastRemoteObject
public class Prou_run extends Thread implements Runnable{

            New_Object  root = null,root2=null,root3=null,root4=null,root5;
              New_Object new_root=null;
            Object xt = null, xt2=null , xt3=null;
            Registry r1,r2;
            RMIClientSocketFactory csf,csf2;
            RMIServerSocketFactory ssf,sf2;


            new_Patryk npal;

 public Prou_run() throws java.rmi.RemoteException, IOException
 {
         if (System.getSecurityManager() == null) {
            System.setSecurityManager(new SecurityManager());
                  }

//            csf = new RMIClientSocketFactory() {
//
//                public Socket createSocket(String host, int port) throws IOException {
//                    return new Socket("rmi://localhost/getchil",1080);
//                }
//            };
//            csf2 = new RMIClientSocketFactory() {
//
//                public Socket createSocket(String host, int port) throws IOException {
//                   return new Socket("rmi://localhost/getchild",1081);
//                }
//            };
//            ssf=new RMIServerSocketFactory() {
//
//                public ServerSocket createServerSocket(int port) throws IOException {
//                    return new ServerSocket(1099);
//                }
//            };// ssf.createServerSocket(1099);
//              sf2=new RMIServerSocketFactory() {
//
//                public ServerSocket createServerSocket(int port) throws IOException {
//                   return new ServerSocket(1098);
//                }
//            };//sf2.createServerSocket(1098);
       try {
         r1=java.rmi.registry.LocateRegistry.createRegistry(1098);
                 r2=java.rmi.registry.LocateRegistry.createRegistry(1099);//, csf2, ssf);
                 java.rmi.registry.LocateRegistry.createRegistry(1097);
                 java.rmi.registry.LocateRegistry.createRegistry(1095);
                 java.rmi.registry.LocateRegistry.createRegistry(1096);
         System.out.println("RMI registry ready.");
      } catch (Exception e) {
         System.out.println("Exception starting RMI registry:");
         e.printStackTrace();
      }
        this.xt = null;this.xt2 = null;this.xt3 = null;
        npal = new new_Patryk();
        System.out.println("sdmmmfxxxxxxxx");

   }






    public void run() {

//while(true){

      try{

//             root =  new_root;
//             xt=npal.getChild((File)new_root.getob(), (int)new_root.geti());
             New_ObjectIMPL sl = new New_ObjectIMPL();
             sl.i=354;
                System.out.println("sdmmmf2");
                //r2
             Naming.rebind("rmi://localhost:1099/getchild",(New_Object) sl);
                System.out.println("sdmmmf3");

         }catch (Exception e) {
       System.out.println("Trouble: " + e);
     }

        while(new_root==null){
            try{
                 //System.out.println("sdmmmf1"   +   new_root.geti());
         new_root = (New_Object) Naming.lookup("rmi://localhost:1080/getchil");
         System.out.println("sdmmmf1"   +   new_root.geti());
            }catch (Exception e) {
       System.out.println("Trouble: " + e);
     }
        }
    }

}

























/**
 *
 * @author austinchuma
 */
public interface New_Object extends java.rmi.Remote {

     public int geti() throws java.rmi.RemoteException;

     public Object getob() throws java.rmi.RemoteException;

     public Object getobchild() throws java.rmi.RemoteException;

      public boolean getbbol() throws java.rmi.RemoteException;

       public byte[] getb() throws java.rmi.RemoteException;



}





public class New_ObjectIMPL extends java.rmi.server.UnicastRemoteObject implements New_Object

{
   Object ob = null,obchild = null;
    int  i=0;
    boolean bol = false;
    byte[] b = null;

    public New_ObjectIMPL() throws RemoteException{
        ob = null;obchild = null;
        i=0;
        bol = false;
        b = null;
    }

    public int geti() throws RemoteException {
       return i;
           }

    public Object getob() throws RemoteException {

       return ob;
    }

    public Object getobchild() throws RemoteException {
       return obchild;
    }

    public boolean getbbol() throws RemoteException {
      return bol;
    }

    public byte[] getb() throws RemoteException {

        return b;

    }


}

RMI bidirectional:

SERVER:

import java.io.IOException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.util.logging.Level;
import java.util.logging.Logger;

public class RMISERVER {

   public RMISERVER() throws IOException {

       Thread t;
        try {
            t = new Prou_run();
            t.start();
        } catch (RemoteException ex) {
            Logger.getLogger(RMISERVER.class.getName()).log(Level.SEVERE, null, ex);
        }

   }


   public static void main(String args[]) throws IOException {
     new RMISERVER();
   }
}


import java.io.File;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.rmi.Naming;
import java.rmi.Remote;
import java.rmi.registry.Registry;
import java.rmi.server.RMIClientSocketFactory;
import java.rmi.server.RMIServerSocketFactory;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.tree.DefaultMutableTreeNode;

//extends java.rmi.server.UnicastRemoteObject
public class Prou_run extends Thread implements Runnable{

            New_Object  root = null,root2=null,root3=null,root4=null,root5;
              New_Object new_root=null;
            Object xt = null, xt2=null , xt3=null;
            Registry r1,r2;
            RMIClientSocketFactory csf,csf2;
            RMIServerSocketFactory ssf,sf2;


            new_Patryk npal;

 public Prou_run() throws java.rmi.RemoteException, IOException
 {
         if (System.getSecurityManager() == null) {
            System.setSecurityManager(new SecurityManager());
                  }

//            csf = new RMIClientSocketFactory() {
//
//                public Socket createSocket(String host, int port) throws IOException {
//                    return new Socket("rmi://localhost/getchil",1080);
//                }
//            };
//            csf2 = new RMIClientSocketFactory() {
//
//                public Socket createSocket(String host, int port) throws IOException {
//                   return new Socket("rmi://localhost/getchild",1081);
//                }
//            };
//            ssf=new RMIServerSocketFactory() {
//
//                public ServerSocket createServerSocket(int port) throws IOException {
//                    return new ServerSocket(1099);
//                }
//            };// ssf.createServerSocket(1099);
//              sf2=new RMIServerSocketFactory() {
//
//                public ServerSocket createServerSocket(int port) throws IOException {
//                   return new ServerSocket(1098);
//                }
//            };//sf2.createServerSocket(1098);
       try {
         r1=java.rmi.registry.LocateRegistry.createRegistry(1098);
                 r2=java.rmi.registry.LocateRegistry.createRegistry(1099);//, csf2, ssf);
                 java.rmi.registry.LocateRegistry.createRegistry(1097);
                 java.rmi.registry.LocateRegistry.createRegistry(1095);
                 java.rmi.registry.LocateRegistry.createRegistry(1096);
         System.out.println("RMI registry ready.");
      } catch (Exception e) {
         System.out.println("Exception starting RMI registry:");
         e.printStackTrace();
      }
        this.xt = null;this.xt2 = null;this.xt3 = null;
        npal = new new_Patryk();
        System.out.println("sdmmmfxxxxxxxx");

   }






    public void run() {

//while(true){

      try{

//             root =  new_root;
//             xt=npal.getChild((File)new_root.getob(), (int)new_root.geti());
             New_ObjectIMPL sl = new New_ObjectIMPL();
             sl.i=354;
                System.out.println("sdmmmf2");
                //r2
             Naming.rebind("rmi://localhost:1099/getchild",(New_Object) sl);
                System.out.println("sdmmmf3");

         }catch (Exception e) {
       System.out.println("Trouble: " + e);
     }

        while(new_root==null){
            try{
                 //System.out.println("sdmmmf1"   +   new_root.geti());
         new_root = (New_Object) Naming.lookup("rmi://localhost:1080/getchil");
         System.out.println("sdmmmf1"   +   new_root.geti());
            }catch (Exception e) {
       System.out.println("Trouble: " + e);
     }
        }
    }

}

























/**
 *
 * @author austinchuma
 */
public interface New_Object extends java.rmi.Remote {

     public int geti() throws java.rmi.RemoteException;

     public Object getob() throws java.rmi.RemoteException;

     public Object getobchild() throws java.rmi.RemoteException;

      public boolean getbbol() throws java.rmi.RemoteException;

       public byte[] getb() throws java.rmi.RemoteException;



}





public class New_ObjectIMPL extends java.rmi.server.UnicastRemoteObject implements New_Object

{
   Object ob = null,obchild = null;
    int  i=0;
    boolean bol = false;
    byte[] b = null;

    public New_ObjectIMPL() throws RemoteException{
        ob = null;obchild = null;
        i=0;
        bol = false;
        b = null;
    }

    public int geti() throws RemoteException {
       return i;
           }

    public Object getob() throws RemoteException {

       return ob;
    }

    public Object getobchild() throws RemoteException {
       return obchild;
    }

    public boolean getbbol() throws RemoteException {
      return bol;
    }

    public byte[] getb() throws RemoteException {

        return b;

    }


}
ゃ懵逼小萝莉 2024-07-29 05:40:55

如果没有第二个 RMI 服务器,B 类如何知道 A 类? 我认为您将需要两台服务器。

How would class B know about class A without a second RMI server though? I think you are going to need two servers.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文