我堅持至少5小時,現在沒有其他度假村,但要問在這裏。我正在編寫一個RMI應用程序。我希望服務器綁定一個遠程對象(這裏是NoteBoardImpl
),這將由客戶端查找。客戶端將偵聽器(此處爲NoteBoardListener
)傳遞給服務器,偵聽器也是客戶端導出的遠程對象。「java.rmi.ConnectException:連接拒絕主機」當導出客戶端對象
我在這裏準備了一個簡單的SSCCE,所以我真的希望有人可以研究它。所有類都在默認包中的相同文件夾中。我知道這是令人沮喪的,我應該將應用程序拆分爲三個罐子,但我希望在這裏儘可能簡單。
遠程接口:
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface INoteBoard extends Remote {
public void test(INoteBoardListener listener) throws RemoteException;
}
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface INoteBoardListener extends Remote {
public void onNewText(String text) throws RemoteException;
}
接口的實現:
import java.rmi.RemoteException;
public class NoteBoardImpl implements INoteBoard {
@Override
public void test(INoteBoardListener listener) throws RemoteException {
listener.onNewText("server call the listener");
}
}
import java.rmi.RemoteException;
public class NoteBoardListener implements INoteBoardListener {
@Override
public void onNewText(String text) throws RemoteException {
System.out.println(text);
}
}
客戶端和服務器:
import java.rmi.Naming;
import java.rmi.server.UnicastRemoteObject;
public class Client {
public static void main(String[] args) {
if (args.length < 2) {
System.out.println("2 arguments required:\nRMI_IP RMI_port");
return;
}
System.setProperty("java.rmi.server.hostname", args[0]);
try {
INoteBoard nb = (INoteBoard) Naming.lookup(String.format("rmi://%s:%s/note", args[0], args[1]));
INoteBoardListener l = (INoteBoardListener) UnicastRemoteObject.exportObject(new NoteBoardListener(), 0);
nb.test(l);
l.onNewText("client invokes listener");
} catch (Exception e) {
e.printStackTrace();
}
}
}
import java.rmi.Naming;
import java.rmi.server.UnicastRemoteObject;
public class Server {
public static void main(String[] args) {
if (args.length < 2) {
System.out.println("2 arguments required:\nRMI_IP RMI_port");
return;
}
System.setProperty("java.rmi.server.hostname", args[0]);
try {
INoteBoard noteBoard = (INoteBoard) UnicastRemoteObject.exportObject(new NoteBoardImpl(), 0);
Naming.rebind(String.format("rmi://%s:%s/note", args[0], args[1]), noteBoard);
} catch (Exception e) {
e.printStackTrace();
}
}
}
我試着模擬用於測試的分佈式系統和運行在客戶端的虛擬機上。主機-VM網絡具有以下規格 - 主機IP = 192.168.56.1,VM IP = 192.168.56.101。
首先,我使用以下命令(預先啓動了rmiregistry 1099
)在本地運行客戶端和服務器。工作目錄是項目的根和編譯的類在bin
目錄:
java -cp bin -Djava.rmi.server.codebase=http://student.agh.edu.pl/~grajewsk/bin/ Server 192.168.56.1 1099
java -cp bin Client 192.168.56.1 1099
和它的工作。
然後我就跑使用相同的命令虛擬機上的客戶端程序,這裏是我得到了異常:
java.rmi.ConnectException: Connection refused to host: 192.168.56.1; nested exception is:
java.net.ConnectException: Connection refused
at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:619)
at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:216)
at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:202)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:128)
at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(RemoteObjectInvocationHandler.java:194)
at java.rmi.server.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:148)
at sun.proxy.$Proxy0.test(Unknown Source)
at Client.main(Client.java:14)
Caused by: java.net.ConnectException: Connection refused
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:327)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:193)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:180)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:384)
at java.net.Socket.connect(Socket.java:546)
at java.net.Socket.connect(Socket.java:495)
at java.net.Socket.<init>(Socket.java:392)
at java.net.Socket.<init>(Socket.java:206)
at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(RMIDirectSocketFactory.java:40)
at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(RMIMasterSocketFactory.java:146)
at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:613)
... 7 more
注意對象如何成功查到的在服務器的註冊表,然後客戶端遠程對象被導出(也是成功的),並且執行在第14行中斷開,我嘗試調用通過客戶端對象的服務器端對象上的方法。
我在任何一個系統上都沒有防火牆,ping在兩個方向都完美無瑕。我知道這裏肯定有一些概念上的問題,當然我誤解了RMI的一些問題。我非常感謝你的幫助。
二進制代碼庫是on my student's server以及the source code。先謝謝你!
可以ping 192.168 .56.1從192.168.56.101開始? – EJP 2013-03-27 05:41:59
是的,正如我寫的「雙向ping完美無瑕」。另外,儘管我運行服務器的機器,我仍可以telnet到rmiregistry和服務器端口,所以我可以在主機或虛擬機上運行服務器,並且可以通過telnet連接到另一臺機器的端口。 – Wojtek 2013-03-27 07:59:30