【问题标题】:Detach and attach RServe connection: Cannot connect分离和附加 RServe 连接:无法连接
【发布时间】:2017-06-12 02:37:38
【问题描述】:

我正在尝试从 Java 中分离并附加一个 RServe 会话。连接到 RServe 完美无缺,但附加会导致异常。

package com.company.korana.r_interface;

import org.rosuda.REngine.Rserve.RConnection;

import com.company.korana.config.Config$;;

public class RToast {
    public static void main(String[] args) throws Exception {
        RConnection rConnection = new RConnection(Config$.MODULE$.rserveHost(), Config$.MODULE$.rservePort());

        rConnection.assign("testVariable", "hello from java");
        rConnection.eval("print('Hi R console from java')"); // <--- this is visible in the R console

        org.rosuda.REngine.Rserve.RSession sessionHandle = rConnection.detach();

        rConnection = sessionHandle.attach(); // <---- this throws

        System.out.println(rConnection.eval("testVariable").asString());
    }
}

线程“主”org.rosuda.REngine.Rserve.RserveException 中的异常: 无法连接:连接被拒绝:连接在 org.rosuda.REngine.Rserve.RConnection.(RConnection.java:90) 在 org.rosuda.REngine.Rserve.RConnection.(RConnection.java:66) 在 org.rosuda.REngine.Rserve.RSession.attach(RSession.java:36) 在 com.company.korana.r_interface.RToast.main(RToast.java:16) 原因: java.net.ConnectException:连接被拒绝:连接在 java.net.DualStackPlainSocketImpl.connect0(Native Method) 在 java.net.DualStackPlainSocketImpl.socketConnect(未知来源)在 java.net.AbstractPlainSocketImpl.doConnect(Unknown Source) at java.net.AbstractPlainSocketImpl.connectToAddress(未知来源)在 java.net.AbstractPlainSocketImpl.connect(Unknown Source) at java.net.PlainSocketImpl.connect(Unknown Source) at java.net.SocksSocketImpl.connect(Unknown Source) 在 java.net.Socket.connect(Unknown Source) 在 java.net.Socket.connect(Unknown Source) 在 java.net.Socket.(未知来源)在 java.net.Socket.(未知来源)在 org.rosuda.REngine.Rserve.RConnection.(RConnection.java:85) ... 还有 3 个

Rserve 使用默认端口在 localhost 上运行。

编辑: 我正在使用以下 Maven 工件:

<dependency>
    <groupId>org.rosuda.REngine</groupId>
    <artifactId>Rserve</artifactId>
    <version>1.8.1</version>
</dependency>

【问题讨论】:

    标签: java r rserve


    【解决方案1】:

    在检查源后,发现 Rserve 会话在分离时会侦听随机分配的端口。

    Rserv.c,第 1781 行

    while ((port = (((int) random()) & 0x7fff)+32768)>65000) {};
    

    因此,客户端和 Rserve 之间需要可访问的端口介于 32768 和 65000 之间。就我而言,这不起作用,因为我使用的是 docker。

    编辑:我构建了一个解决方案,可以在不打开大量端口的情况下将 Rserve 与 docker 一起使用(这与 docker 不兼容)。下面的狙击手替换了我的 install.packages("Rserve"):

    RUN wget https://www.rforge.net/src/contrib/Rserve_1.8-5.tar.gz
    RUN tar -xf Rserve_1.8-5.tar.gz
    RUN rm Rserve_1.8-5.tar.gz
    RUN sed -i '1763s/.*/\t\tint port = 53000;/' /Rserve/src/Rserv.c
    RUN sed -i '1781s/.*//' /Rserve/src/Rserv.c
    RUN sed -i '1793s/.*/\t\tif (port>53100) {/' /Rserve/src/Rserv.c
    RUN tar -czvf Rserve_1.8-5.tar.gz /Rserve
    RUN R CMD INSTALL Rserve_1.8-5.tar.gz
    

    这会修改 Rserve 源,以便在 [53000, 53100[ 范围内使用端口,这在我的情况下就足够了。

    【讨论】: