如何在使用 RMI 时共享输入流或输出流



我有一个服务器端应用程序,我试图通过RMI共享对它的访问。 该应用程序具有"项目"的抽象表示形式,该表示通常表示文件,但几乎可以表示任意数据,包括流(流无线电,来自传感器的流数据(。 因此,任何"项目"都可以通过输入流(以及指示文件大小的方法(如果可以知道(进行访问(。

虽然 RMI 对于应用程序的其余部分已经足够了,但它实际上无法处理输入流。

令我震惊的是,在使用RMI时访问输入流的需求一定是一个常见问题。所以我想知道:推荐的解决方案是什么?

注意 我需要客户端同时发送和接收输入流,并且序列化为字节数组是不可行的,因为其中一些实际上表示数据流,而不仅仅是文件。

我使用 RMIIO 库通过 RMI 共享流。

查看课程:com.healthmarketscience.rmiio.RemoteInputStreamcom.healthmarketscience.rmiio.RemoteOutputStream

另请参阅:使用 RMIIO 的远程流式处理参考

除了传递流,不如传递一种"流句柄"吗?也就是说,一个对象本身不是流,但可以按需生成流。像这样:

public interface StreamHandle extends Serializable {
    public InputStream getStream();
}
public class WebStreamHandle implements StreamHandle {
    private URL url;
    public InputStream getStream() {
        return url.openStream();
    }
}
public class SocketStreamHandle implements StreamHandle {
    private String host;
    private int port;
    public InputStream getStream() {
        return new Socket(host, port).getInputStream();
    }
}
public class BufferStreamHandle implements StreamHandle {
    private byte[] buffer;
    public InputStream getStream() {
        return new ByteArrayInputStream(buffer);
    }
}

关键是要确保代码能够独立于执行它的机器生成流。因此,您无法引用文件(除非您知道该文件将位于每台计算机上,或者是 UNC 路径(,但您可以引用网络上的资源。

然后,您可以传递句柄,并按需生成流。

我刚刚将一个轻量级解决方案Serializable InputStream推送到Github,用于通过RMI传递InputStream,这在概念上与RMIIO非常相似。这可能会解决您的问题。使用该库,您可以轻松包装InputStream以使其可序列化:

serializableStream = new SerializableInputStream(originalInputStream);

基本上,它利用ObjectOutputStream的行为在实现Serializable的类上调用特殊方法(如果存在(:

private void writeObject(java.io.ObjectOutputStream out) throws IOException;
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException;

使用这些方法,SerializableInputStream将从委托InputStream读取的块转发到 RMI 框架使用的处理ObjectOutputStream。然后,这些块在另一端反序列化(到内存缓存或临时文件 - 这是可配置的,具体取决于您的需求(。

至于你的要求...

"其中一些实际上确实代表了数据流,而不仅仅是一个文件">

。我相信要么你需要进一步澄清你的需求,要么重新考虑RMI是否真的适合你的用例:我看不出通过基于方法调用的接口发送(可能永无止境的(数据流如何为你工作。

最新更新