最近闲来无事补充了下自己的短板,学习了下RMI,本来以为很简单的事,没想到遇到几个问题还是花了一段时间,在这记录下,测试demo代码附在后面。
RMI的原理在这不说了,百度或Google很多,只说下遇到的问题,具体问题解决方法我这说的不清楚也可以Google下。
说明:Centos6是装载VMware虚拟机中的固定IP,防火墙开,网络适配器为桥接模式;Windows10;registry port :1234;socket port:12345(开始不知道有这种端口)。
2、Server运行环境都是Windows,Client运行环境是Centos6,单网卡,运行正常。
3、Server运行环境都是Windows,Client运行环境是Centos6,多网卡,运行不正常;原因:Server运行时使用的ip和Linux使用的ip不在同一个网段下,解决方法:指定Server的hostname:java.rmi.server.hostname=要绑定的ip
4、Server运行环境是Centos6,Client运行环境是Centos6或Windows,运行不正常;
①注册端口1234没有放开,报
java.rmi.ConnectIOException: Exception creating connection to: 192.168.1.16; nested exception is:
java.net.NoRouteToHostException: No route to host (Host unreachable)
或java.rmi.ConnectException: Connection refused to host: 192.168.1.16; nested exception is:
java.net.ConnectException: Connection timed out: connect;服务器开放端口1234;
②服务器端没有指定hostname,java.rmi.server.hostname=服务器的ip或者机器名,如果指定是机器名的话需要将机器名对应的ip写入在Client的hosts文件里。可以指定-D 或catalina_Opts或代码中加入System.setProperty("java.rmi.server.hostname", "服务器的ip或者机器名")
③数据传输Socket端口12345没有开放,放开12345端口即可。根据错误日志,可以看出Client和Server也是通过Socket来传输数据的。此处Socket端口默认是随机的,每次服务端启动时端口可能是变化的,所以如果防火墙启动的话最好在代码中指定。主要在这花的时间比较长,因为根据异常从网上找的信息大多是指定hostname,就一直在这纠结了。关闭防火墙后好使,根据netstat命令一看果然两个端口。还是对RMI内部机制不熟悉导致。
异常信息:
java.rmi.ConnectException: Connection refused to host: 192.168.1.16; nested exception is:
java.net.ConnectException: Connection timed out: connect
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(Unknown Source)
at java.rmi.server.RemoteObjectInvocationHandler.invoke(Unknown Source)
at com.sun.proxy.$Proxy0.sayHello(Unknown Source)
at com.springmvc.rmi.RMIClient.main(RMIClient.java:18)
Caused by: java.net.ConnectException: Connection timed out: connect
at java.net.DualStackPlainSocketImpl.connect0(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(Unknown Source)
at java.net.AbstractPlainSocketImpl.doConnect(Unknown Source)
at java.net.AbstractPlainSocketImpl.connectToAddress(Unknown Source)
at java.net.AbstractPlainSocketImpl.connect(Unknown Source)
at java.net.PlainSocketImpl.connect(Unknown Source)
at java.net.SocksSocketImpl.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at java.net.Socket.<init>(Unknown Source)
at java.net.Socket.<init>(Unknown Source)
at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(Unknown Source)
at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(Unknown Source)
... 8 more
解决以上问题后:
Server端:
[root@localhost Desktop]# java -jar -Djava.rmi.server.hostname=rmi rmiserver.jar
输入ip(localhost输入1):
1
rmi://localhost:1234/irmi
>>>>>>远程RMI绑定成功
Client端:[root@rmi demo]# java -jar rmiclient.jar
输入ip:
192.168.1.16
和服务器说点话:
你好
ip:192.168.1.15-->client:你好,给你7
Server端:
[root@localhost Desktop]# java -jar -Djava.rmi.server.hostname=rmi rmiserver.jar
输入ip(localhost输入1):
1
rmi://localhost:1234/irmi
>>>>>>远程RMI绑定成功
host:192.168.1.15
ip:192.168.1.15-->welcome:你好
OK!
以下是测试Demo代码:
Client:
package com.springmvc.rmi; import java.io.IOException; import java.rmi.Naming; import java.rmi.NotBoundException; import java.util.Scanner; public class RMIClient { public static String url = "rmi://%s:1234/irmi"; public static void main(String[] args) { Scanner s = new Scanner(System.in); try { System.out.println("输入服务器ip:"); url = String.format(url, s.next()); IRMIInterface irmi = (IRMIInterface) Naming.lookup(url); System.out.println("和服务器说点话:"); irmi.sayHello(s.next()); System.out.println(irmi.getSomeThing("client")); } catch (NotBoundException | IOException e) { e.printStackTrace(); } finally { s.close(); } } }Server:
package com.springmvc.rmi; import java.io.IOException; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.UnknownHostException; import java.rmi.AlreadyBoundException; import java.rmi.Naming; import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; import java.rmi.server.RMISocketFactory; import java.rmi.server.ServerNotActiveException; import java.rmi.server.UnicastRemoteObject; import java.util.Scanner; /** * 服务器端 * * @Filename: RMIServer.java * @Version: 1.0 * @Author: yanrp * @Email: * */ public class RMIServer extends UnicastRemoteObject implements IRMIInterface { public static String url = "rmi://%s:1234/irmi"; /** *Comment for <code>serialVersionUID</code> */ private static final long serialVersionUID = -7279580357318512456L; protected RMIServer() throws RemoteException { super(); } @Override public void sayHello(String name) throws RemoteException { try { String host = getClientHost(); String ip = InetAddress.getByName(host).getHostAddress(); System.out.println("host:" + host); System.out.println("ip:" + ip + "-->welcome:" + name); } catch (ServerNotActiveException | UnknownHostException e) { e.printStackTrace(); } } @Override public String getSomeThing(String name) throws RemoteException { String ret = ""; try { String ip = InetAddress.getByName(getClientHost()).getHostAddress(); ret = "ip:" + ip + "-->" + name + ":你好,给你" + (int) (Math.random() * 100); } catch (UnknownHostException | ServerNotActiveException e) { e.printStackTrace(); } return ret; } public static void main(String[] args) { Scanner s = new Scanner(System.in); try { System.out.println("输入ip(localhost输入1):"); String ip = s.next(); if ("1".equals(ip)) { ip = "localhost"; } url = String.format(url, ip); System.out.println(url); //System.setProperty("java.rmi.server.hostname", "192.168.1.15"); CustomRMISocketFactory socketFactory = new CustomRMISocketFactory(12345); RMISocketFactory.setSocketFactory(socketFactory); IRMIInterface irmi = new RMIServer(); LocateRegistry.createRegistry(1234); Naming.bind(url, irmi); System.out.println(">>>>>>远程RMI绑定成功"); } catch (AlreadyBoundException | IOException e) { e.printStackTrace(); } finally { s.close(); } } } /** * SocketFactory 指定Socket端口工厂类 * * @Filename: RMIServer.java * @Version: 1.0 * @Author: yanrp * @Email: * */ class CustomRMISocketFactory extends RMISocketFactory { private int p; CustomRMISocketFactory(int port) { this.p = port; } @Override public Socket createSocket(String host, int port) throws IOException { if (port == 0) port = this.p; return new Socket(host, port); } @Override public ServerSocket createServerSocket(int port) throws IOException { if (port == 0) port = this.p; return new ServerSocket(port); } }
Interface:package com.springmvc.rmi; import java.rmi.Remote; import java.rmi.RemoteException; /** * 开放接口 * * @Filename: IRMIInterface.java * @Version: 1.0 * @Author: yanrp * @Email: * */ public interface IRMIInterface extends Remote { void sayHello(String name) throws RemoteException; String getSomeThing(String name) throws RemoteException; }
1760

被折叠的 条评论
为什么被折叠?



