如何在 C# 中使用通过 http 进行远程处理来返回执行分块的 byte[]?
在通过 http 的 .Net 远程处理中,我们通过执行 SerilizationInfo.AddValue(SerializationInfoValueName, ((MemoryStream)writer.BaseStream).GetBuffer(), typeof(byte[])) 调用将 byte[] 返回给客户端。
然而,有时 byte[] 大小变得太大并导致 OutOfMemory 异常。唯一的补救措施似乎是利用某种形式的分块。迁移到 WCF 似乎是最合乎逻辑的,但这在不久的将来是不可能的。
那么关于如何实现通用分块解决方案有什么建议吗?
In .Net remoting over http, we return a byte[] back to the client by doing a SerilizationInfo.AddValue(SerializationInfoValueName, ((MemoryStream)writer.BaseStream).GetBuffer(), typeof(byte[])) call.
However, sometimes the byte[] size gets too big and causes an OutOfMemory exception. The only remedy seems to be utilize some form of chunking. A move to WCF seems most logical, however that's not possible in the near future.
So any suggestions on how to implement a generic chunking solution?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
更安全的方法是仅远程传输从服务器返回的对象上的流。 Stream 扩展了 MarshalByRefObject,因此如果您在发送到客户端的对象中包含对打开的 Stream 的引用(例如,指向要发送的文件数据或缓冲区),则当您调用方法时客户端将回调到服务器在流代理上。这样,客户端可以使用它想要的任何缓冲区大小(在合理范围内)来移动数据。
A more secure way to do it is to just remote a stream on the object you're returning from the server. Stream extends MarshalByRefObject, so if you include a reference to an open Stream (eg, pointing at the file data or buffer you want to send) in an object that's sent to the client, the client will call back to the server when you call methods on the stream proxy. This way, the client can use whatever buffer sizes it wants (within reason) to move the data around.
没有内置的分块。您需要自己实施它。它应该非常简单。
像下面这样的一些接口应该可以解决这个问题:
当调用
GetFile()
时,服务器可以根据Guid 将文件“缓存”在
充当密钥。然后这个Guid可以返回给客户端,以便它可以发出进一步的请求来下载文件的实际块。Dictionary
中如果 chunkIndex 超过该 Guid/文件的块数,
GetFileChunk()
应返回 null。块的大小取决于您。您可以在响应能力和性能之间进行选择。块越大,性能就越好。但是,如果您正在更新 GUI 上的进度条或其他内容,那么“响应能力”当然会受到不利影响。尝试尝试最有效的方法。
替代接口可能类似于:
这意味着客户端可以决定它希望下载的块的大小。然后你可以实施某种扩展策略。
There is no built-in chunking. You will need to implement it yourself. It should be pretty straightforward.
Some interface like the following should do the trick:
When
GetFile()
is called the server can 'cache' the file in aDictionary<>
against aGuid
that acts as the key. Then thisGuid
can be returned back to the client so that it can make further requests to download the actual chunks of the file.GetFileChunk()
should return null if the chunkIndex exceeds the number of chunks for that Guid / file.The size of the chunks if up to you. You have a choice between responsiveness and performance. The larger the chunks the better the performance will be. But if you are updating a progress bar or something on a GUI then of course the 'responsiveness' will be adversely affected. Try experimenting with what works best.
An alternative interface may be something like:
This would mean the client could decide the size of the chunks it wishes to download. And then you could implement some sort of scaling strategy.
该解决方案实际上取决于服务器上的资源是否可以轻松“查找”。例如,如果您要创建一个简单的远程处理服务,仅访问文件并返回其内容,那么这将是一个非常简单的服务。您只需让客户端传入要检索的数据的所需偏移量和长度。
但是,如果在服务器上生成数据更加复杂,并且您需要在一个逻辑调用中完成调用,则可能需要深入研究 诸如自定义接收器之类的东西。
我已经很长时间没有使用 .NET 远程处理了,但是由于 Stream 派生自 MarshalByRefObject,因此您可以通过引用客户端来返回流。然而,这可能会变得棘手,因为您现在使用的服务器端对象的生命周期比逻辑操作长,这可能会引入可伸缩性问题,并且如果您决定稍后升级,则在 WCF 中没有直接类比。
就其价值而言,WCF 确实对流式传输数据提供本机支持它的内置协议。
The solution would really depend on whether or not the resource at the server is easily "seekable". For example if you were to create a simple remoting service that simply accessed a file and returned its contents, that would be a pretty simple one. You'd just have the client pass in a desired offset and length of the data to retrieve.
But if the data is more complicated to produce on the server and you need the call to complete in one logical call, you might need to delve into things like custom sinks.
It's been a very long time since I've used .NET remoting, but since Stream derives from MarshalByRefObject, you may be able to return a stream by reference to the client. However, this can get tricky as you're now using server-side objects with a lifetime longer than the logical operation which can introduce scalability issues and has no direct analogy in WCF if you decide to upgrade later.
For what it's worth, WCF does have native support for streaming data over its built in protocols.