首页 > 解决方案 > 有没有人在使用 Java-Prolog 连接器时得到“java.net.SocketException: Connection reset”

问题描述

我想知道是否有人使用过 Java-Prolog 连接器(https://sewiki.iai.uni-bonn.de/research/pdt/connector/start)并且之前遇到过“java.net.SocketException: Connection reset”。

我的代码就像

PrologProcess process = Connector.newPrologProcess();
while(condition) {
    process.restart();
    PrologSession session = process.getSession();
    session.queryOnce(assertz(...));
    String query = ...;
    Map<String, Object> query_result = session.queryOnce(query);
    session.dispose();
}

所以我基本上想做的是迭代地构建会话并在条件成立时获取查询结果。但是,它并不总是有效,而且似乎如果迭代次数过多,我可能会收到“java.net.SocketException:连接重置”并且无法获取会话。有没有人使用相同的工具并遇到相同的问题?谢谢!

以下是详细的异常消息:

org.cs3.prolog.connector.process.PrologProcessException: Failed to obtain session
    at org.cs3.prolog.connector.internal.process.AbstractPrologProcess.getSession(AbstractPrologProcess.java:371)
    at org.cs3.prolog.connector.internal.process.AbstractPrologProcess.getSession(AbstractPrologProcess.java:346)
    at com.example.demo.Search.is_done(Search.java:5363)
    at com.example.demo.Search.main(Search.java:1156)
Caused by: org.cs3.prolog.connector.process.PrologProcessException: java.io.IOException: EndOfStream read while waiting for OK
    at org.cs3.prolog.connector.internal.lifecycle.AbstractState.error(AbstractState.java:117)
    at org.cs3.prolog.connector.internal.lifecycle.LifeCycle$3.run(LifeCycle.java:226)
    at org.cs3.prolog.connector.internal.lifecycle.LifeCycle$DispatcherThread.run(LifeCycle.java:59)
Caused by: java.io.IOException: EndOfStream read while waiting for OK
    at org.cs3.prolog.connector.internal.process.socket.SocketClient.readUntil(SocketClient.java:185)
    at org.cs3.prolog.connector.internal.process.socket.SocketClient.readUntil(SocketClient.java:142)
    at org.cs3.prolog.connector.internal.process.socket.SocketClient.reset(SocketClient.java:105)
    at org.cs3.prolog.connector.internal.process.socket.SocketClient.<init>(SocketClient.java:60)
    at org.cs3.prolog.connector.internal.process.socket.SocketPrologProcess.getSession_impl(SocketPrologProcess.java:163)
    at org.cs3.prolog.connector.internal.process.AbstractPrologProcess.getSession_internal(AbstractPrologProcess.java:379)
    at org.cs3.prolog.connector.internal.process.AbstractPrologProcess.getSession(AbstractPrologProcess.java:369)
    at org.cs3.prolog.connector.internal.process.AbstractPrologProcess.getSession(AbstractPrologProcess.java:346)
    at com.example.demo.Search.is_done(Search.java:5363)
    at com.example.demo.Search.main(Search.java:1156)

java.net.SocketException: Connection reset
    at java.net.SocketInputStream.read(SocketInputStream.java:209)
    at java.net.SocketInputStream.read(SocketInputStream.java:141)
    at org.cs3.prolog.connector.internal.process.socket.InputStreamProxy.read(InputStreamProxy.java:79)
    at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
    at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
    at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
    at java.io.InputStreamReader.read(InputStreamReader.java:184)
    at java.io.BufferedReader.fill(BufferedReader.java:161)
    at java.io.BufferedReader.readLine(BufferedReader.java:324)
    at java.io.BufferedReader.readLine(BufferedReader.java:389)
    at org.cs3.prolog.connector.internal.process.socket.SocketClient.readUntil(SocketClient.java:174)
    at org.cs3.prolog.connector.internal.process.socket.SocketClient.readUntil(SocketClient.java:142)
    at org.cs3.prolog.connector.internal.process.socket.SocketClient.reset(SocketClient.java:105)
    at org.cs3.prolog.connector.internal.process.socket.SocketClient.<init>(SocketClient.java:60)
    at org.cs3.prolog.connector.internal.process.socket.SocketClient.<init>(SocketClient.java:53)
    at org.cs3.prolog.connector.internal.process.socket.SocketServerStartAndStopStrategy.getSocketClient(SocketServerStartAndStopStrategy.java:355)
    at org.cs3.prolog.connector.internal.process.socket.SocketServerStartAndStopStrategy.stopSocketServer(SocketServerStartAndStopStrategy.java:335)
    at org.cs3.prolog.connector.internal.process.socket.SocketServerStartAndStopStrategy.stopServer(SocketServerStartAndStopStrategy.java:326)
    at org.cs3.prolog.connector.internal.process.AbstractPrologProcess$MyLifeCycle.stopServer(AbstractPrologProcess.java:234)
    at org.cs3.prolog.connector.internal.lifecycle.ErrorState$1.run(ErrorState.java:48)
    at org.cs3.prolog.connector.internal.lifecycle.LifeCycle$DispatcherThread.run(LifeCycle.java:59)

标签: javaprolog

解决方案


即使使用最新版本的 Java 库,问题似乎仍然存在。正如@David Tonhofer 建议的那样,这个问题似乎是由于套接字连接出了问题。虽然我仍然找不到完全解决这个问题的方法,但我在这里提出了一个有点幼稚和直接的解决方案,以防有人遇到同样的问题。

下面是示例代码:

{
    ...
    PrologProcess process = Connector.newPrologProcess();
    while(condition) {
        myFunction(process,...);
    }
    Runtime.getRuntime().exec("taskkill /IM swipl-win.exe /F");
    ...
}

private static int myFunction(PrologProcess process) {    
    try {
        process.restart();
        PrologSession session = process.getSession();
        try {
            session.queryOnce(assertz(...));
            String query = ...;
            Map<String, Object> query_result = session.queryOnce(query);
            session.dispose();
            ...
        }
        catch(Exception) {
            ...
        }
    }
    try {
        process = Connector.newPrologProcess();
        return myFunction(process);
    }
}

所以想法是每当发生“获取会话失败”异常时使用递归创建一个新的Prolog进程,并在程序结束时使用“Runtime.getRuntime().exec(”taskkill /IM swipl-win.exe /F”);” 杀死在此过程中创建的所有 swipl-win.exe,并且可能由于异常而保留在那里。


推荐阅读