我有一个服务器端应用程序,我试图通过RMI共享访问权限。该应用程序具有“项目”的抽象表示,其最常表示文件但可以表示几乎任何任意数据,包括流(流式传输,来自传感器的流数据)。因此,任何“项目”都可以通过InputStream访问(如果可以知道文件大小,还可以指示文件大小)。
虽然RMI足以满足应用程序的其余部分,但它实际上无法处理InputStreams。
令我感到震惊的是,在使用RMI时访问InputStreams的必要性必然是一个常见问题。所以我想知道: 有哪些推荐的解决方案?
注意我需要客户端发送和接收输入流并且序列化为字节数组是不可行的,因为其中一些实际上确实代表了数据流,而不仅仅是文件。
答案 0 :(得分:4)
我使用RMIIO库通过RMI共享流。
请参阅课程:com.healthmarketscience.rmiio.RemoteInputStream
和com.healthmarketscience.rmiio.RemoteOutputStream
答案 1 :(得分:0)
您可以传递一种“流句柄”,而不是传递流吗?也就是说,一个对象本身不是流,但可以按需生成流。类似的东西:
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路径),但你可以参考网络上的资源。
然后,您可以传递句柄,并根据需要生成流。
答案 2 :(得分:0)
我刚刚将一个轻量级解决方案Serializable InputStream推送到Github,以便在概念上与RMIIO非常相似的RMI上传递InputStream
。这可能会解决您的问题。使用该库,您可以轻松地包裹InputStream
以使其可序列化:
serializableStream = new SerializableInputStream(originalInputStream);
基本上,它利用ObjectOutputStream
的行为在实现Serializable
的类上调用special methods(如果存在):
private void writeObject(java.io.ObjectOutputStream out) throws IOException;
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException;
使用这些方法,SerializableInputStream
转发从委托InputStream
读取的块到RMI框架使用的处理ObjectOutputStream
中。然后这些块在另一端被反序列化(进入内存缓存或临时文件 - 这是可配置的,取决于您的需要)。
至于你的要求......
“其中一些实际上确实代表了一个数据流,而不仅仅是一个文件”
...我相信您需要进一步澄清您的需求或重新考虑RMI是否真的适合您的用例:我无法看到如何通过方法调用发送(可能永无止境的)数据流基于界面的界面可以帮到你。