我正在尝试重新编写一些基本的设计模式。我只有代码片段,没有完整的运行代码示例。一个叫做代理模式。
我只想通过远程调用方法。这是我的简单代码:
WebService.java
public class WebService extends UnicastRemoteObject implements IRemote {
private static final long serialVersionUID = 1L;
public static void main(String[] args) {
try {
IRemote service = new WebService();
Naming.rebind("RemoteCalculator", service);
} catch (Exception e) {
e.printStackTrace();
}
}
/** No arg default constructor */
public WebService() throws RemoteException { }
/** Methods of remote interface */
@Override
public double getRoot(double v) throws RemoteException {
return Math.sqrt(v);
}
}
...其中IRemote是一个简单的接口,用于扩展远程接口并定义单个示例方法的签名(getRoot(double))。
现在连接到遥控器的类:
TestProxy.java
public class TestProxy implements Remote{
/**
* @param args
*/
public static void main(String[] args) {
new TestProxy().go(args[0]);
}
public TestProxy() {}
public void go(String ip) {
try {
System.out.println("Trying to lookup for service ...");
IRemote service = (IRemote) Naming.lookup("//" + ip + "/RemoteCalculator");
System.out.println("done");
double d = service.getRoot(5.0);
System.out.println(d);
} catch (Exception e) {
e.printStackTrace();
}
}
}
我正在运行rmiregistry.exe并通过rmic.exe创建了我的WebService_Stub.class,如某些文档中所示。 本地连接127.0.0.1作为(ip-)参数工作正常。但即使端口(1099)已打开并通过telnet检查,也无法通过互联网进行连接。
当我从命令行开始时:
java net.mypackage.remote.TestProxy 78.2.2.2
它总是给出结果:
尝试查找服务...已完成java.rmi.ConnectException: 连接拒绝主持人:192.168.1.51;嵌套的例外是: java.net.ConnectException:连接超时 at sun.rmi.transport.tcp.TCPEndpoint.newSocket(Unknown Source) at sun.rmi.transport.tcp.TCPChannel.createConnection(Unknown Source) at sun.rmi.transport.tcp.TCPChannel.newConnection(Unknown Source) at sun.rmi.server.UnicastRef.invoke(Unknown Source) at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(Unkn 自己的来源) at java.rmi.server.RemoteObjectInvocationHandler.invoke(Unknown Source) 在$ Proxy1.getRoot(未知来源) 在net.gerdsmeier.remote.TestProxy.go(TestProxy.java:39) at net.gerdsmeier.remote.TestProxy.main(TestProxy.java:22)引起:java.net.ConnectException:连接超时 at java.net.PlainSocketImpl.socketConnect(Native Method) at java.net.AbstractPlainSocketImpl.doConnect(Unknown Source) at java.net.AbstractPlainSocketImpl.connectToAddress(Unknown Source) 在java.net.AbstractPlainSocketImpl.connect(未知来源) 在java.net.SocksSocketImpl.connect(未知来源) 在java.net.Socket.connect(未知来源) 在java.net.Socket.connect(未知来源) 在java.net.Socket。(未知来源) 在java.net.Socket。(未知来源) at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(Unknown S 乌尔斯河) at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(Unknown S 乌尔斯河) ... 9更多
其中192.168.1.51是我的本地ip-adress(即端口转发工作正常)。
答案 0 :(得分:0)
好的,我猜你的WebService是在NAT之后,你已经在1099上设置了端口转发以进入RMI注册表。这还不够。远程对象将在不同于1099的端口上进行侦听。如果未设置端口转发到此端口,则永远不会连接,因此double d = service.getRoot(5.0)
行处的异常。
问题是要转发哪个端口?如果您没有指定端口,RMI将随机选择一个高端口。但您可以使用UnicastRemoteObject构造函数的版本指定端口。因此,您可以选择端口号,执行IRemote service = new WebService([portnumber]);
并在该端口上设置端口转发。
看看它是否会削减它!
答案 1 :(得分:-1)
好吧,我已经解决了部分问题。它落后于服务器存根的逻辑:
在服务器端,我们必须通过添加行
来添加有关全局主机名的信息System.setProperty("java.rmi.server.hostname",Util.getGlobalAddress().getHostAddress());
...... Util类看起来像:
public class Util{
/**
* Finds this computer's global IP address
*
* @return The global IP address, or null if a problem occurred
*/
public static Inet4Address getGlobalAddress()
{
try
{
URLConnection uc = new URL( "http://vallentinsource.com/globalip.php" ).openConnection();
BufferedReader br = new BufferedReader( new InputStreamReader( uc.getInputStream() ) );
return ( Inet4Address ) InetAddress.getByName( br.readLine() );
}
catch( MalformedURLException e )
{
e.printStackTrace();
}
catch( IOException e )
{
e.printStackTrace();
}
return null;
}
}
现在它在一个方向上工作,即像
这样的客户端调用service.printName("Pete");
在服务器端正常工作。另一方面......
d = service.getRoot(5.0);
System.out.println(d);
...在客户端上还没有工作。它不会引发错误,但我们没有得到结果。然而。你可以通过添加客户端ip adress / hostname来修复它:
System.setProperty("java.rmi.client.hostname", "ip.of.client.pc");
但服务器事先无法知道所有客户端地址。无论如何:这是一种解决方法,在某些情况下可能会有所帮助。