0

我正在尝试使用 Java 中的套接字将 RDF/XML 从客户端发送到服务器。当我发送信息时,服务器程序挂起并且不接收信息,除非我关闭客户端的 Socket 或 OutputStream。即使我在客户端刷新 OutputStream,除非我关闭 Socket/Stream,否则服务器也不会接收数据。我想在不关闭套接字的情况下发送信息。这是客户端的一些示例代码(使用 Sesame):

import java.io.*;
import java.net.*;
import org.openrdf.rio.*;
import org.openrdf.rio.helpers.*;
import org.openrdf.model.URI;
import org.openrdf.model.Model;
import org.openrdf.model.ValueFactory;
import org.openrdf.model.Statement;
import org.openrdf.model.impl.*;
import org.openrdf.model.vocabulary.*;
public class SimpleRDFClient {
    private Socket socket = null;
    public static void main(String[] args) {
        new SimpleRDFClient(args[0],Integer.parseInt(args[1])).launch();
    }
    public SimpleRDFClient(String host, int port) {
        try {
            socket = new Socket(host,port);
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
    public void launch() {
        try {
            OutputStream out = socket.getOutputStream();
            BufferedOutputStream dos = new BufferedOutputStream(out);
            Model model = new LinkedHashModel();
            ValueFactory factory = new ValueFactoryImpl();
            URI clive = factory.createURI("http://www.site.org/cliveAnderson");
            Statement st = factory.createStatement(clive, RDF.TYPE, FOAF.PERSON);
            model.add(st);
            Rio.write(model,dos,RDFFormat.RDFXML);
            dos.flush();
            //Some other stuff
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}   

和服务器处理程序:

import java.io.*;
import java.net.*;
import org.openrdf.rio.*;
import org.openrdf.rio.helpers.*;
import org.openrdf.model.*;
import org.openrdf.model.impl.*;

public class SimpleRDFSHandler implements Handler {
    public void handleConnection(Socket socket) {
        Model model = null;
        try {
            InputStream in = socket.getInputStream();

            model = Rio.parse(in,"www.blah.com",RDFFormat.RDFXML);

            for (Statement st: model) {
                System.out.println(st);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

问题似乎来自 Rio.parse() 方法挂起(我认为是因为它不知道输入何时结束)。当我以类似的方式使用 Jena api 时,我遇到了类似的问题,即使用 Model.write(outputstream,format) 和 Model.read(inputstream,format) 而不是 Rio。我已经查看了源代码和 javadoc 多年但无法解决问题。我想这一定是我误解了一些简单的事情。有任何想法吗?

4

1 回答 1

1

我认为这绝不是 Jena/Sesame 的特定问题,而是围绕您使用套接字的 Java 问题。实际上有你不想关闭套接字的实际原因吗?

我不明白为什么这会是可取的,除非您想连续发布数据并在服务器端收到数据时对其进行处理?如果是这种情况,Jena 和 Sesame 都具有专门允许您控制数据在解析时发生的情况的 API,这样您就不必依赖于在处理数据之前完成读取调用。

还有为什么要使用套接字,Sesame 和 Jena 都具有全面的 HTTP 集成,这比滚动您自己的基于套接字的服务器和客户端更容易使用和部署。

丑陋的哈克解决方案

如果你真的必须这样做,那么有一个解决方法,但它有点可怕和脆弱,我强烈建议你不要这样做。

在客户端写入数据后,写入指示流结束的字节序列。在服务器端,使用自定义 InputStream 实现包装套接字流,该实现识别此序列并在看到它时停止返回数据。这应该允许期望流完成的 Jena/Sesame 代码正常运行。

需要仔细选择字节序列,使其不会自然地出现在数据中。

老实说,这是一个糟糕的主意,如果您的目标是连续发布数据,这并不能真正解决您的问题,因为除非您将服务器端套接字处理代码放在一个while (true)循环中,否则您只会泄漏服务器端的套接字可能是另一个坏主意。

于 2013-07-10T22:13:20.080 回答