RMI RemoteException - PullRequest
       16

RMI RemoteException

6 голосов
/ 01 мая 2010

Есть идеи, почему я получаю RemoteException при попытке вызвать методы на Unix-машине из Windows?
Я нахожусь в сети и не думаю, что это из-за проблемы с брандмауэром, так как я могу выполнить «telnet» из Windows в окно Unix после запуска сервера RMI в окне unix. Я также не мог понять, почему происходит локальный петлевой IP?

Трассировка стека:

RemoteException occured, details java.rmi.ConnectException: Connection refused to host: 127.0.0.1; nested exception is: 
    java.net.ConnectException: Connection refused: connect
java.rmi.ConnectException: Connection refused to host: 127.0.0.1; nested exception is: 
    java.net.ConnectException: Connection refused: connect

Большое спасибо заранее.

Ответы [ 2 ]

12 голосов
/ 01 мая 2010

Возможно, ваше имя хоста не настроено должным образом на вашем Linux-компьютере. Бьюсь об заклад, если вы ping $(hostname) из вашей коробки Linux, он будет пинг 127.0.0.1. Обычно это происходит из-за записи в вашем файле /etc/hosts.

Есть несколько способов решить проблему. Трудным путем было бы заставить ваш Linux-сервер правильно разрешить свое собственное имя хоста на свой IP-адрес. Вы можете отредактировать файл /etc/hosts, настроить свой DNS-сервер, что бы вы ни делали. Проблема в том, что, хотя это может сделать вещи технически правильными, вы рискуете сломать вещи, которые опирались на старое поведение.

Путь наименьшего изменения будет , установите системное свойство java.rmi.server.hostname в качестве имени хоста или IP-адреса вашего Linux-бокса. (т.е. java -Djava.rmi.server.hostname=$(hostname) ...).

Почему?

Сервер регистрации Java RMI на самом деле является сервером регистрации всей сети. Объекты на других машинах могут связываться с этим реестром.

Когда удаленный объект зарегистрирован, регистрация включает сетевой адрес как часть регистрации. По умолчанию используемый им адрес - это «IP-адрес локального хоста в формате« пунктирная четверка ».» В вашей настройке этот адрес 127.0.0.1.

Когда ваш ящик Windows связывается со службой регистрации для адреса удаленного объекта, он возвращается 127.0.0.1. Затем он пытается связаться с удаленным объектом по этому адресу. Вот почему это происходит по адресу обратной связи.

0 голосов
/ 13 декабря 2013

Я предлагаю решение на основе настроенной RMISocketFactory.

Как объяснено на Sun Site, вы можете предоставить свой собственный SocketFactory: http://docs.oracle.com/javase/7/docs/technotes/guides/rmi/socketfactory/

Мое решение использует этот механизм для создания перехвата клиентского сокета и заменит полученный хост (127.0.0.1) на хороший IP, хорошо известный клиенту.

Остальная часть механизма связи по-прежнему основана на стандартах Java RMI.

В этой реализации экспортеру не нужно знать свой собственный IP, который иногда бывает непростым (несколько сетевых интерфейсов ...)

Вот классы дерева, Фабрика, Сервер и Клиент. Класс Hello и интерфейс также загружены, чтобы быть исчерпывающими.

Надеюсь, это будет полезно

SocketFactory:

import java.io.IOException;
import java.io.Serializable;
import java.net.ServerSocket;
import java.net.Socket;
import java.rmi.server.RMISocketFactory;

/**
 * Socket Factory for RMI calls.
 * 
 * This classe, instanciated from server when RMI objects are exported, is send
 * to the client who use it (transparently) for create sockets which call remote objects.
 * 
 * This implementation give the ability to modify dynamically the target host cible.
 * 
 * The host will not be aware of it's own IP.
 */
public class MySocketFactory extends RMISocketFactory implements Serializable {

    /**Target host for RMI calls, setted by caller. */
    private static String server = "localhost";

    /**
     * Create a client socket, replacing required host by the host setted when the service is called,
     * via {@link #setServer(String)}.
     * The host received is usually 127.0.0.1, depending on property java.rmi.server.hostname on the exporter.
     */
    @Override
    public Socket createSocket(String host, int port) throws IOException {
        System.out.println("change host from " + host + " to " + server);
        return getFactory().createSocket(server, port);
    }

    /**
     * Create a server socket.
     */
    @Override
    public ServerSocket createServerSocket(int port) throws IOException {
        return getFactory().createServerSocket(port);
    }

    /**
     * Use default RMI factory.
     */
    private RMISocketFactory getFactory() {
        return RMISocketFactory.getDefaultSocketFactory();
    }

    /**
     * Save the target host. This method must be called before use of a service (before Naming.lookup).
     */
    public static void setServer(String host) {
        server = host;
    }

}

Экспортер:

import java.io.IOException;
import java.rmi.Naming;
import java.rmi.RMISecurityManager;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.RMISocketFactory;
import java.rmi.server.UnicastRemoteObject;

/**
 * RmiExport
 */
public class MyRmiExporter {

    /**
     * java -Djava.security.policy=java.policy MyRmiExporter
     */
    public static void main(String[] args) throws RemoteException, IOException {
        System.setSecurityManager(new RMISecurityManager());

        Hello export = new HelloImpl();
        RMISocketFactory sf = new MySocketFactory();

        UnicastRemoteObject.unexportObject(export, true);
        Remote stub = UnicastRemoteObject.exportObject(export, 0, sf, sf);
        String url = "rmi://0.0.0.0:" + Registry.REGISTRY_PORT + "/Hello";

        LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
        Naming.rebind(url, stub);

        System.out.println("Exported " + url);
    }

}

Клиент:

import java.io.IOException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.registry.Registry;

public class MyClient {

    /**
     * java MyClient localhost
     */
    public static void main(String[] args) throws IOException, NotBoundException, InterruptedException {
        String host = args[0];
        MySocketFactory.setServer(host);
        String url = "rmi://" + host + ":" + Registry.REGISTRY_PORT + "/Hello";;
        System.out.println("look up " + url);
        Hello proxy = (Hello) Naming.lookup(url);
        System.out.println("OK, remote getted !");
        System.out.println(proxy.hello("bonjour"));
    }
}

Боб:

import java.io.Serializable;
import java.rmi.Remote;
import java.rmi.RemoteException;

public interface Hello extends Remote, Serializable {

    String hello(String mess) throws RemoteException;

}

Impl:

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

public class HelloImpl extends UnicastRemoteObject implements Hello {

    public HelloImpl() throws RemoteException {
    }

    @Override
    public String hello(String mess) throws RemoteException {
        return "hello : " + mess;
    }

}

последний и последний, java.policy:

grant {
    permission java.security.AllPermission;
};
...