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

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

BR,

马库斯

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

我在cleint和server之间实现了2路RMI,服务器使用Registry公开它的存根

  1. 客户端获取服务器的存根
  2. 然后客户端将其存根作为Observer放入服务器的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); } } } 

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

但是,如果你有很多这样的RMI调用,那么你可能会遇到性能问题。

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

网络服务器

 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; } 

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

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

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

某些RMI服务支持回调或侦听器,允许服务器在同一连接上异步调用客户端。 (对不起,我不记得这样做的开放库的名称,快速谷歌不是很有帮助)标准RMI不支持这一点,而是你需要将客户端暴露为RMI服务。

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; } }