package rmi; import java.rmi.Remote; import java.rmi.RemoteException; import java.util.List; public interface PersonService extends Remote { public List<Person> getList() throws RemoteException; }
package rmi.server; import rmi.Person; import rmi.PersonService; import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; import java.util.LinkedList; import java.util.List; public class PersonServiceImpl extends UnicastRemoteObject implements PersonService { public PersonServiceImpl() throws RemoteException { super(); } @Override public List<Person> getList() throws RemoteException { List<Person> personList = new LinkedList<Person>(); personList.add(new Person("a")); personList.add(new Person("b")); personList.add(new Person("c")); return personList; } }
package rmi.server; import rmi.PersonService; import rmi.server.PersonServiceImpl; import java.net.MalformedURLException; import java.net.UnknownHostException; import java.rmi.Naming; import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; public class RmiServer { public static void main(String[] args) throws RemoteException, MalformedURLException, UnknownHostException { System.setProperty("java.rmi.server.hostname", "aaa"); // System.setProperty("java.rmi.server.hostname", "centos"); // System.setProperty("java.rmi.server.hostname", "localhost"); // System.setProperty("java.rmi.server.hostname", "127.0.0.1"); PersonService personService = new PersonServiceImpl(); //注册通讯端口 // System.out.println(java.net.InetAddress.getLocalHost()); LocateRegistry.createRegistry(6600); //注册通讯路径 // Naming.rebind("rmi://127.0.0.1:6600/PersonService", personService); Naming.rebind("rmi://localhost:6600/PersonService", personService); // Naming.rebind("rmi://centos:6600/PersonService", personService); // Naming.rebind("rmi://10.10.4.42:6600/PersonService", personService); System.out.println("Service Start!"); } }
package rmi.client; import rmi.Person; import rmi.PersonService; import java.net.MalformedURLException; import java.rmi.Naming; import java.rmi.NotBoundException; import java.rmi.RemoteException; import java.util.List; public class RmiClient { public static void main(String[] args) throws RemoteException, MalformedURLException, NotBoundException { // PersonService personService = (PersonService) Naming.lookup("rmi://10.10.4.42:6600/PersonService"); PersonService personService = (PersonService) Naming.lookup("rmi://168.1.191.119:6600/PersonService"); List<Person> personList = personService.getList(); for (Person person : personList) { System.out.println(person); } } }
rmi服务在windows上可以被客户端正常查找并使用,但是,当rmi在linux上时候,则客户端可能出现拒绝访问地址127.0.1.1的问题。
原因是由于客户端首先通过socket连接到rmi服务器时候,rmi服务器会向客户端发送一个“rmi服务ip”,此“rmi服务ip”用于客户端查找对应资源,rmi server会通过java.net.InetAddress.getLocalHost取本机ip作为“rmi服务ip”返回给客户端,在windows下取到的是正确的对外ip,而在linux下取到的是127.0.1.1,这样如果客户端拿到的是127.0.1.1就会去客户端本机查找,所以就会出错。
修订方案:rmi server绑定的时候必需要指定自身真实的对外ip,而不是localhost或127.0.0.1,如可以使用“rmi://10.10.191.119:6600/**”进行绑定,
另一种比较好的方式是通过rmi提供的参数-Djava.rmi.server.hostname或系统属性java.rmi.server.hostname设置成本机真实的ip,如
-Djava.rmi.server.hostname=10.10.191.119
或
System.setProperty("java.rmi.server.hostname", "10.10.191.119");
PS:弄清楚了服务器向客户端传递“rmi服务ip”的原理后就好解决了,
即便是rmi服务器设置:System.setProperty("java.rmi.server.hostname", "aaa");
只要客户端的hosts表中配置了:10.10.191.119 aaa
也是可以的,原理就是rmi server会将java.rmi.server.hostname的值传递给客户端,客户端根据得到的值去查找服务。
如果拿到的是ip地址则直接访问,如果拿到的是字符串主机名则去本机的hosts中查找对应的ip。