Java 如何在使用RMI时共享InputStream或OutputStream?
我有一个服务器端应用程序,我正试图通过RMI共享对该应用程序的访问。该应用程序具有“项”的抽象表示,该项最常用于表示文件,但可以表示几乎任何任意数据,包括流(流广播、来自传感器的流数据)。因此,任何“项”都是通过InputStream访问的(如果可以知道,还可以通过一个方法指示文件大小) 虽然RMI对于应用程序的其余部分已经足够了,但它实际上无法处理InputStreams 我突然意识到,在使用RMI时访问InputStreams必须是一个常见的问题。所以我想知道: 建议的解决方案是什么 注意:我需要客户端同时发送和接收输入流,并且序列化到字节数组是不可行的,因为其中一些实际上代表数据流,而不仅仅是文件。我使用库通过RMI共享流 参见类:Java 如何在使用RMI时共享InputStream或OutputStream?,java,inputstream,rmi,outputstream,Java,Inputstream,Rmi,Outputstream,我有一个服务器端应用程序,我正试图通过RMI共享对该应用程序的访问。该应用程序具有“项”的抽象表示,该项最常用于表示文件,但可以表示几乎任何任意数据,包括流(流广播、来自传感器的流数据)。因此,任何“项”都是通过InputStream访问的(如果可以知道,还可以通过一个方法指示文件大小) 虽然RMI对于应用程序的其余部分已经足够了,但它实际上无法处理InputStreams 我突然意识到,在使用RMI时访问InputStreams必须是一个常见的问题。所以我想知道: 建议的解决方案是什么 注意:
com.healthmarketscience.rmio.RemoteInputStream
和com.healthmarketscience.rmio.RemoteOutputStream
另请参见:我使用库通过RMI共享流
参见类:com.healthmarketscience.rmio.RemoteInputStream
和com.healthmarketscience.rmio.RemoteOutputStream
另请参见:您可以传递某种“流句柄”而不是传递流吗?也就是说,对象本身不是流,但可以按需生成流。比如:
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路径),但您可以引用网络上的资源
然后,您可以传递句柄,并根据需要生成流。您可以传递一种“流句柄”而不是传递流吗?也就是说,对象本身不是流,但可以按需生成流。比如:
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路径),但您可以引用网络上的资源
然后,您可以传递句柄,并根据需要生成流。我刚刚向Github推出了一个轻量级解决方案,用于通过RMI传递
InputStream
,该解决方案在概念上非常类似于。这可能会解决你的问题。使用该库,您可以轻松包装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是否真的是适合您的用例的技术:我看不出如何发送(可能是永无止境的)通过基于方法调用的接口的数据流可能适合您。我刚刚向Github推出了一个轻量级解决方案,用于通过RMI传递
InputStream
,这在概念上非常类似于。这可能会解决你的问题。使用该库,您可以轻松包装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是否真的是适合您的用例的技术:我看不出如何发送(可能是永无止境的)通过基于方法调用的接口的数据流可能适合您。您可能感兴趣:您可能感兴趣:只要服务器连接/合并了一个web服务器以提供对URL的访问,这就可以工作。我在问题中没有说明这一点,但服务器必须始终充当代理,客户端不得自行获取数据。啊哈。我在想,在这种情况下,你的应用程序正在讨论源自远方的流(例如来自远程传感器或无线电台),在这种情况下,哪台机器检索它们并不重要。如果不是这样,那么这种方法没有多大帮助,DRCB的答案是更好的。只要服务器连接/合并了web服务器以提供对URL的访问,这种方法就会起作用。我在问题中没有说明这一点,但服务器必须始终充当代理,客户端不得自行获取数据。啊哈。我在想,在这种情况下,你的应用程序正在讨论源自远方的流(例如来自远程传感器或无线电台),在这种情况下,哪台机器检索它们并不重要。如果不是这样的话,那么这种方法没有多大帮助,DRCB的答案是更好的