2010-04-30 3 views
6

Windows에서 Unix 시스템의 메소드를 호출하는 중 RemoteException이 발생하는 이유는 무엇입니까?
유닉스 박스에서 RMI 서버를 시작한 후 윈도우에서 유닉스 박스로 "텔넷"을 할 수 있기 때문에 나는 네트워크 내부에 있는데 이것이 방화벽 문제로 생각하지 않는다. 또한 로컬 루프백 IP로가는 이유를 이해할 수 없었습니다.RMI RemoteException

스택 추적 : 사전에

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 

많은 감사합니다.

+1

당신의 클라이언트는 Y를 생각하는 것 같다 우리 서버는 localhost에 있지만 자세한 내용없이 이유를 말할 수는 없습니다. 클라이언트 코드를 게시 할 수 있습니까? – mdma

답변

12

Linux 상자에 호스트 이름이 제대로 구성되어 있지 않은 것 같습니다. 나는 당신의 리눅스 박스에서 ping $(hostname)이 있다면, 그것은 127.0.0.1이라고 ping 할 것이다. 보통 이것은 /etc/hosts 파일의 항목 때문에 발생합니다.

문제를 해결하는 데는 몇 가지 방법이 있습니다. 어려운 방법은 리눅스 박스가 자체 호스트 이름을 IP 주소로 올바르게 해석하도록하는 것입니다. /etc/hosts 파일을 편집하고 DNS 서버를 설정하고 수행해야하는 작업을 수행 할 수 있습니다. 문제는 이것이 기술적으로보다 정확한 것을 만들지 만, 예전의 행동에 의존하는 것을 깨뜨릴 위험이 있다는 것입니다.

최소 변경 경로는 Linux 상자의 호스트 이름 또는 IP 주소에 set the system property java.rmi.server.hostname입니다. (즉, java -Djava.rmi.server.hostname=$(hostname) ...).

왜?

Java RMI 등록 서버는 실제로 네트워크 와이드 등록 서버입니다. 다른 컴퓨터의 개체는이 레지스트리에 바인딩 될 수 있습니다.

원격 개체가 등록 될 때 등록에는 등록의 일부로 네트워크 주소가 포함됩니다. 기본적으로 사용하는 주소는 '점 분리 쿼드'형식의 '로컬 호스트의 IP 주소'입니다. 설정시이 주소는 127.0.0.1입니다.

Windows 상자가 원격 개체의 주소 등록 서비스에 연결하면 다시 127.0.0.1이됩니다. 그런 다음 해당 주소의 원격 객체에 접속을 시도합니다. 루프백 주소로가는 이유입니다.

+1

레지스트리에는 아무런 관련이 없습니다. 스텁에 어떤 정보가 포함되는지에 관한 것입니다. 그것은 레지스트리없이 일어날 수 있습니다. 그 외에도 Dave의 대답은 정확합니다. 가장 좋은 방법은/etc 호스트 파일을 수정하는 것입니다. 일시적인 해결책은 서버 JVM *에서 java.rmi.server.hostname *을 설정하는 것입니다. 근본적으로 이는 특정 Linux 배포판의 문제점입니다. 이것은 Javadoc의 RMI FAQ에있는 A.1 항목입니다. – EJP

+0

안녕하세요, Dave, 내가 말한대로 시스템 속성을 설정했지만 여전히 동일한 예외가 발생합니다. 변경하기 전이나 후에도 레지스트리 객체를 찾아 성공적으로 list() 메소드를 호출 할 수있었습니다. 나는이 오류의 원인이 무엇일까? –

+0

@Gabriel - 서버 (Unix) 측 또는 클라이언트 (Windows) 측에서 등록 정보를 설정 했습니까? 서버 측에 있어야합니다. – leedm777

0

사용자 지정 RMISocketFactory를 기반으로하는 솔루션을 제안합니다.

처럼이 일 사이트에 설명, 자신의 SocketFactory 제공 할 수 http://docs.oracle.com/javase/7/docs/technotes/guides/rmi/socketfactory/

내 솔루션 사용을 차단 클라이언트 소켓의 작성이 mecanism을하고, 대체 호스트가 아니라, 좋은 IP에 의해 (127.0.0.1) 접수 클라이언트가 알고있는.

나머지 통신 메커니즘은 여전히 ​​Java rmi 표준을 기반으로합니다. 이 구현으로

, 수출은 때때로 더 쉽게 그 자체 IP (다중 네트워크 인터페이스 ...) 여기

트리 클래스, 공장, 서버 및 클라이언트입니다 알 필요가 없습니다 . Hello 클래스와 인터페이스는 모두 포괄적으로 업로드됩니다.

는해야 희망 utile

의 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; 
};