0

在通过 http 进行远程处理的 .Net 中,我们通过执行 SerilizationInfo.AddValue(SerializationInfoValueName, ((MemoryStream)writer.BaseStream).GetBuffer(), typeof(byte[])) 调用将 byte[] 返回给客户端。

但是,有时 byte[] 大小会变得太大并导致 OutOfMemory 异常。唯一的补救措施似乎是利用某种形式的分块。转向 WCF 似乎是最合乎逻辑的,但在不久的将来这是不可能的。

那么关于如何实现通用分块解决方案的任何建议?

4

3 回答 3

1

一种更安全的方法是在您从服务器返回的对象上远程传输一个流。Stream 扩展 MarshalByRefObject,因此如果您在发送给客户端的对象中包含对打开的 Stream 的引用(例如,指向您要发送的文件数据或缓冲区),则客户端将在您调用方法时回调服务器在流代理上。这样,客户端可以使用它想要的任何缓冲区大小(在合理范围内)来移动数据。

于 2009-12-28T22:25:17.303 回答
0

没有内置的分块。您将需要自己实现它。它应该很简单。

像下面这样的一些界面应该可以解决问题:

Guid GetFile(string filename);
Guid GetFile(string filename, out int chunkCount);
byte[] GetFileChunk(Guid id, int chunkIndex);

GetFile()被调用时,服务器可以将文件“缓存”在作为密钥的Dictionary<>a中。Guid然后Guid可以将其返回给客户端,以便它可以进一步请求下载文件的实际块。

GetFileChunk()如果 chunkIndex 超过该 Guid / 文件的块数,则应返回 null。

块的大小由您决定。您可以在响应能力和性能之间做出选择。块越大,性能就越好。但是,如果您要更新 GUI 上的进度条或其他内容,那么“响应性”当然会受到不利影响。尝试尝试最有效的方法。

替代接口可能类似于:

Guid GetFile(string filename, out ulong numOfBytes);
byte[] GetFileData(Guid id, ulong index, ulong count);

这意味着客户端可以决定它希望下载的块的大小。然后你可以实施某种扩展策略。

于 2009-12-28T22:20:51.013 回答
0

解决方案实际上取决于服务器上的资源是否易于“查找”。例如,如果您要创建一个简单的远程服务,它只是访问一个文件并返回其内容,那将是一个非常简单的服务。您只需让客户端传入所需的偏移量和要检索的数据长度。

但是,如果在服务器上生成的数据更复杂,并且您需要在一个逻辑调用中完成调用,您可能需要深入研究自定义接收器之类的东西

自从我使用 .NET 远程处理以来已经有很长时间了,但是由于 Stream 派生自 MarshalByRefObject,您可以通过引用客户端来返回流。但是,这可能会变得很棘手,因为您现在使用的服务器端对象的生命周期比逻辑操作长,这可能会引入可伸缩性问题,并且如果您决定稍后升级,则在 WCF 中没有直接的类比。

值得一提的是, WCF 确实通过其内置协议对流数据提供了原生支持。

于 2009-12-28T22:24:43.737 回答