简体   繁体   English

使用RMI时如何共享InputStream或OutputStream?

[英]How to share an InputStream or an OutputStream while using RMI?

I have a server side application to which I'm attempting to share access to via RMI. 我有一个服务器端应用程序,试图通过RMI共享访问权限。 The application has an abstract representation of an "item" which is most commonly represents a file but could represent almost any arbitrary data including stream (streaming radio, streaming data from a sensor). 该应用程序具有“项目”的抽象表示,该项目最通常表示一个文件,但几乎可以表示任何数据,包括流(流广播,来自传感器的流数据)。 Consequently any "item" is accessed through an InputStream (alongside a method to indicate the file size if it can be known). 因此,可以通过InputStream访问任何“项目”(如果可以知道,还可以使用一种方法来指示文件大小)。

While RMI is sufficient for the rest of the application, it really can't handle InputStreams. 尽管RMI足以满足其余应用程序的需求,但它实际上无法处理InputStreams。

It strikes me that the need to access InputStreams while using RMI must be a common problem. 令我惊讶的是,在使用RMI时访问InputStreams的需求必定是一个普遍的问题。 So I was wondering: What are the recommended solutions? 所以我想知道:推荐的解决方案是什么?

Note I need the client to both send and receive input streams and serializing to a byte array is not viable because some of them actually do represent a stream of data, not just a file. 请注意,我需要客户端同时发送和接收输入流,并且序列化为字节数组是不可行的,因为其中一些实际上确实表示数据流,而不仅仅是文件。

I use RMIIO library to share streams over RMI. 我使用RMIIO库通过RMI共享流。

See classes: com.healthmarketscience.rmiio.RemoteInputStream and com.healthmarketscience.rmiio.RemoteOutputStream 请参阅以下类: com.healthmarketscience.rmiio.RemoteInputStreamcom.healthmarketscience.rmiio.RemoteOutputStream

See also: Remote streaming reference with RMIIO 另请参阅: RMIIO的远程流参考

Rather than passing streams, can you pass a sort of 'stream handle'? 除了传递流之外,您还可以传递一种“流句柄”吗? That is, an object which is not a stream itself, but can produce a stream on demand. 也就是说,对象本身不是流,而是可以按需生成流。 Something like: 就像是:

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);
    }
}

The key thing would be to ensure that the code was able to produce a stream independently of the machine it was executed on. 关键是要确保代码能够独立于其执行的机器而产生流。 So, you couldn't refer to a file (unless it was file you knew would be on every machine, or was a UNC path), but you can refer to resources on the network. 因此,您无法引用文件(除非该文件是您知道将在每台计算机上使用的文件,或者是UNC路径),但是您可以引用网络上的资源。

Then, you could pass the handles around, and produce the streams on demand. 然后,您可以传递手柄,并按需生成流。

I just pushed a lightweight solution Serializable InputStream to Github for passing an InputStream over RMI that is conceptually very similar to RMIIO . 我只是将轻量级解决方案Serializable InputStream推送到Github,以通过RMI传递InputStream ,该输入流在概念上与RMIIO非常相似。 This might solve your problem. 这可能会解决您的问题。 With that library you can easily wrap your InputStream to make it serializable: 使用该库,您可以轻松包装InputStream使其可序列化:

serializableStream = new SerializableInputStream(originalInputStream);

Basically it leverages the behavior of ObjectOutputStream to call special methods (if present) on classes that implement Serializable : 基本上,它利用ObjectOutputStream的行为在实现Serializable类上调用特殊方法 (如果存在):

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

Using these methods, the SerializableInputStream forwards chunks read from the delegate InputStream into the processing ObjectOutputStream used by the RMI framework. 使用这些方法, SerializableInputStream将从委托InputStream读取的块转发到RMI框架使用的处理ObjectOutputStream These chunks then get deserialized on the other end (either into an in-memory cache or into a temp file - that's configurable and depends on your needs). 然后,这些块会在另一端反序列化(进入内存缓存或临时文件中,这是可配置的,具体取决于您的需求)。

As for your requirement that... 至于你的要求...

"some of them actually do represent a stream of data, not just a file" “其中一些确实代表数据流,而不仅仅是文件”

...I believe that either you need to further clarify your needs or reconsider if RMI is really the technique that suits your use case: I cannot see how sending (potentially never-ending) streams of data over a method-invocation-based interface could work out for you. ...我相信您要么需要进一步澄清您的需求,要么重新考虑RMI是否真的适合您的用例:我无法看到如何通过基于方法调用的接口发送(可能永无止境)数据流可以为您解决。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM