2012-02-16 4 views
1

두 번째 JVM을 시작하는 프로젝트가 있습니다. 현재 저는 RMI를 사용하여 둘 사이에서 통신하고 있습니다. 내 컴퓨터에서 잘 작동합니다.로컬 호스트 전용 RMI?

방화벽 규칙을 변경할 수있는 권한이없는 Windows 7 컴퓨터에이 프로젝트를 배포 할 수 있어야합니다.

레지스트리 (높은 임의 포트의 첫 번째 JVM에서 시작됨)가 이러한 시스템에서 서버 소켓을 열 수 없도록 차단되었습니다.

로컬 연결 만 수신하도록 RMI를 제한 할 수있는 방법이 있습니까? 그와 같은 Windows 방화벽은 멋질 것입니까?

또는 대체 기능이 거의 필요하지 않은 대체 IPC 방식이 있습니까?

건배.

+0

웹 서비스 (8080 포트에서 작동)가 인기를 얻은 바로 그 이유입니다. –

+0

이것이 어떻게 도움이 될지 모르겠습니다. 나는 둘 사이에 로컬 HTTP 연결을 열 수 있지만, 그 단계에서 나는 소켓을 통해 객체 스트림을 확실히 실행하는 것이 더 낫겠습니까? – FlightOfStairs

답변

3

이것은 처음 나타나는 것보다 더 까다 롭습니다. 원하는 것은 주소 인의 레지스트리를 수신하지만 포트는 수신하지 못하도록 제한하는 것입니다. 문제는 RMI 레지스트리 구현 프로그램 (rmiregistry)이 실제로 청취하는 IP 주소를 제한하는 메커니즘을 제공하지 않는다는 것입니다. 항상 사용 가능한 모든 네트워크 인터페이스에서 수신 대기합니다. 이를 제한하는 실제적인 메커니즘은 두 가지뿐입니다.

  1. 방화벽 규칙을 사용하십시오. 이것은 정직한 일반적인 기술이지만 배포하는 동안 구성이 필요합니다.
  2. 은 로컬 컴퓨터에서만 도달 할 수있는 소켓에 대해 불평하지 않기 때문에 올바른 IP 주소 (즉, localhost, 127.0.0.1)에 제한을 적용하는 특수 버전의 RMI 레지스트리를 사용하십시오.

이 두 번째 옵션은 내가 간략하게 설명합니다. 실제로 대부분의 복잡성을 기존 클래스에 위임 할 수 있으므로 매우 간단합니다.

import java.io.IOException; 
import java.net.*; 
import java.rmi.server.*; 
import java.rmi.registry.LocateRegistry; 

public class RestrictedRMIRegistry implements RMIServerSocketFactory { 
    public static void main(String... args) throws IOException { 
     int port = (args.length == 0 ? 1099 : Integer.parseInt(args[0], 10)); 
     RMIClientSocketFactory csf = RMISocketFactory.getDefaultSocketFactory(); 
     RMIServerSocketFactory ssf = new RestrictedRMIRegistry(); 

     LocateRegistry.createRegistry(port, csf, ssf); 
    } 

    public ServerSocket createServerSocket(int port) throws IOException { 
     // Tricky bit; make a server socket with bound address 
     return new ServerSocket(port, 0, InetAddress.getLocalHost()); 
    } 
} 

이 정상 rmiregistry 구현 사이의 유일한 차이점은이 모두 클라이언트와 서버 소켓 팩토리에 대한 기본값을 사용한다는 것입니다.

+0

정확히 내가 무엇을 찾고 있었는지 – FlightOfStairs

+0

이 문제는 보안 문제로 인해 RMI를 localhost로 제한하려는 비슷한 문제에 대해 매우 유용하게 사용되었습니다. 그러나 포트 1098 소켓을 제한해야한다는 사실을 발견했습니다. 행해지 다. 이 같은 소켓 팩토리를 리모트 클래스의 constructor에 건네줍니다. ; 공용 클래스 RemoteStatistics는 UnicastRemoteObject의 { 개인 RemoteStatistics을() RemoteException을 발생 { 슈퍼 (1098, 널 (null), RestrictableRMIRegistry.getInstance()) 확장 } – Fanjita

+0

죄송합니다. 저는 SO 주석 마크 업을하는 멍청한 사람입니다. 코드를 올바르게 형식화하는 데 어려움을 겪고 있습니다. – Fanjita

0

일반적으로 아웃 바운드 연결에 대해 열리는 HTTP 대신 웹 서비스라고하는 것이 좋습니다.

인바운드 연결에 문제가 있습니다. "올바른"아키텍처는 방화벽 뒤에 배치 된 프로세스가 인바운드 HTTP 연결이 제한되지 않는 어딘가에 설치된 서버 인 3 차 프로세스를 통해 서로 이야기 할 때라고 생각합니다. 따라서 방화벽 뒤의 두 구성 요소는 서버에 대한 아웃 바운드 HTTP 연결 만 수행합니다.

+0

그 중 아무 것도 할 필요가 없습니다. 시스템의 모든 부분이 하나의 시스템에서 실행 중이며 외부 자원이 필요하지 않습니다.문제는 Windows 방화벽 블록 rmiregistry, 내가 로컬 IPC에 사용하고있다. – FlightOfStairs

0

레지스트리 (또는 계획에 관련된 다른 Java 프로세스)를 시작할 때 java.rmi.server.hostname 속성을 127.0.0.1으로 설정해보십시오.

+0

레지스트리 스텁이 원격으로 수집되지 않고 원격으로 수집되지 않기 때문에 나쁜 생각은 아니지만 레지스트리에는 영향을 미치지 않습니다. 등록 정보가 설정된 JVM에서 내 보낸 다른 원격 스텁 만 영향을받습니다. SocketPermission 'accept'를 제한하는 .policy 파일도 또 다른 가능성이 있습니다. – EJP

+0

흠, 네 말이 맞아. 그 세트로'rmiregistry'를 실행할 때, 여전히 열리는 포트가 열립니다. :-(나는 수정하는 방법을 알고 있지만, 코드가 필요하기 때문에 약간의 글을 쓸 것입니다. –

+0

java.rmi.server.hostname'은 수신 포트를 제어하지 않고 스텁에 쓰여지는 것을 제어합니다 'LocateRegistry.getRegistry()'는 당신이 지정한 host : port로부터 레지스트리 스텁을 로컬로 생성하기 때문에 레지스트리의 JVM에서'java.rmi.server.hostname'의 설정은 그 스텁에 영향을 줄 수 없습니다. 레지스트리 또는 다른 원격 개체를 가져 와서 127.0.0.1에 바인딩 된 포트를 열려면 내보낼 때 RMIServerSocketFactory를 지정해야합니다. – EJP