タツノオトシゴのブログ

主にJavaに関するものです。

RMIのサーバとクライアントを別々なPCに設置する場合

  • サーバとクライアントを別なPC(IPアドレス)で動作させる場合、クライアントからサーバ側へ接続したときに、以下のような例外が出力される。エラーの内容を見ると、デフォルトでは同一のIPアドレスから接続されることを前提としていることがわかる。
 java.rmi.ConnectException: Connection refused to host: 127.0.0.1; nested exception is:
 java.net.ConnectException: Connection refused ‥ 
  • 回避するには、JVMオプション「java.rmi.server.hostname」としてサーバ側自身のIPアドレスを起動時(RMI起動前)に与える。

Java内で「java.rmi.server.hostname」指定する場合

  • RMIを起動するstatic メソッドで指定する。
    • ただし、InteAddressを利用するため、DNSなど自身で自身のアドレスを解決できる環境でないといけない。
    • Windowsなどではたいてい問題ないが、Linuxなど通常設定では自身のアドレスを取得できない場合があるので、shellスクリプトで取得する。
  • ループバックアドレスだと意味がないので、その場合は値を設定しない。
  • また、下記のshellスクリプトと併用する場合があるので、既にJVMオプションが指定されている場合は処理をスキップする。
    /** JVMオプション(JVMオプション) */
    public static final String JVM_OPT_RMI = "java.rmi.server.hostname";
    
    private static final Logger logger = LoggerFactory.getLogger(RmiServer.class);
    
    static {
        
        /*
         * RMIで外部から接続する場合、自身のアドレスを起動オプションで指定する必要がある。
         *  Linuxからは起動shell内で指定する。
         */
        try {
            String jvmOpt = System.getProperty(JVM_OPT_RMI);
            if(jvmOpt == null) {
                InetAddress ia = InetAddress.getLocalHost();
                String ipAdress = ia.getHostAddress();
                if(!StringUtils.equalsIgnoreCase(ipAdress, "127.0.0.1")
                        && !StringUtils.equalsIgnoreCase(ipAdress, "localhost")) {
                    System.out.printf("...RMI Server Hostname : [%s]\n", ipAdress);
                    System.setProperty(JVM_OPT_RMI, ipAdress);
                }
            }
        } catch(Exception e) {
            logger.error(String.format("fail setting JVM OPS [%s]", JVM_OPT_RMI), e);
        }
    }
shellスクリプトで「java.rmi.server.hostname」指定する場合
    IPADDRESS=`/sbin/ifconfig  | grep 'inet addr:' | grep -v '127.0.0.1'`
    IPADDRESS=`echo $IPADDRESS | cut -d " " -f 2 | awk -F":" '{print $2}'`
    if [ "$IPADDRESS" == "" ]; then
        echo "fail starting server for not getting ipaddress.";
        exit 1
    else
        echo "...RMI Server hostname [$IPADDRESS]"
    fi
    
    # Javaの起動
    ${JAVA_HOME}/bin/java -Djava.rmi.server.hostname=$IPADDRESS ....