我想在两个类(A 和 B)之间共享一些信息,它们在不同的 java 程序中运行。我不想编写一个完整的通信协议,而是为此目的使用 java 内置 rmi 类。目前 B 类能够远程运行属于 A 类的方法。是否可以在 A 类中使用相同的“连接”来调用 B 类的方法?否则我可能不得不实施第二个 rmi 服务......
BR,
马库斯
我想在两个类(A 和 B)之间共享一些信息,它们在不同的 java 程序中运行。我不想编写一个完整的通信协议,而是为此目的使用 java 内置 rmi 类。目前 B 类能够远程运行属于 A 类的方法。是否可以在 A 类中使用相同的“连接”来调用 B 类的方法?否则我可能不得不实施第二个 rmi 服务......
BR,
马库斯
如果B
实现Remote
,它可以导出并作为 RMI 调用中的参数传递给A
. 在这种情况下,不需要B
在 RMI 注册表中注册,因为客户端被显式地传递了对它的引用。
我在客户端和服务器之间实现了 2 路 RMI,服务器使用 Registry 公开其存根
下面的代码将给出一个更好的主意
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 以来已经有一段时间了,但是 IIRC 如果 B 类实现java.rmi.Remote
并将对自身实例的引用作为参数传递给 A 类中的方法,那么 A 类应该接收一个存根并且调用它的方法将是在原始实例上调用。
但是,如果您有很多这样的 RMI 调用来回调用,您可能会遇到性能问题。
如果您将B
作为参数传递给 in 的方法A
,然后使用该引用调用方法,B
我相当肯定反向连接已建立,并且我相当肯定 RMI Registry 是为B
驻留的 JVM 创建的。在某些时候,这给我们带来了一些特别严格的防火墙规则的麻烦。我们的代码看起来有点像
网络服务器
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;
}
但是,如果没有第二个 RMI 服务器,B 类如何知道 A 类呢?我认为您将需要两台服务器。
两个 JVM 都需要实现 RMI 服务。但这确实很容易查看 java.rmi 中的各种类。
您不能以某种方式使用一个 RMI 连接并进行双向通信。
一些 RMI 服务支持回调或侦听器,它们允许服务器异步调用同一连接下的客户端。(抱歉,我不记得执行此操作的开放库的名称,快速 google 不是很有帮助)标准 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;
}
}