Che*_*eso 13 .net streaming wcf
在WCF中,我不能将服务写入客户端接收的流吗?
WCF支持流请求,响应或两者.我想支持一种情况,即数据生成器(流式传输请求时的客户端或流式响应时的服务器)可以在流上写入.这支持吗?
类比是来自ASP.NET请求的Response.OutputStream.在ASPNET中,任何页面都可以在输出流上调用Write,并且客户端会接收内容.我可以在WCF服务中执行类似的操作 - 在客户端接收的流上调用Write吗?
让我用WCF插图解释一下.WCF中最简单的Streaming示例是将FileStream返回给客户端的服务.这是一个流式响应.实现此目的的服务器代码如下:
[ServiceContract]
public interface IStreamService
{
[OperationContract]
Stream GetData(string fileName);
}
public class StreamService : IStreamService
{
public Stream GetData(string filename)
{
return new FileStream(filename, FileMode.Open)
}
}
Run Code Online (Sandbox Code Playgroud)
客户端代码是这样的:
StreamDemo.StreamServiceClient client =
new WcfStreamDemoClient.StreamDemo.StreamServiceClient();
Stream str = client.GetData(@"c:\path\on\server\myfile.dat");
do {
b = str.ReadByte(); //read next byte from stream
...
} while (b != -1);
Run Code Online (Sandbox Code Playgroud)
(例子来自http://blog.joachim.at/?p=33)
清楚吧?服务器将Stream返回给客户端,客户端调用Read.
客户端是否可以提供Stream,并且服务器可以在其上调用Write?
换句话说,不是拉模型 - 客户端从服务器提取数据 - 它是推模型,客户端提供"接收"流并且服务器写入其中.服务器端代码可能类似于:
[ServiceContract]
public interface IStreamWriterService
{
[OperationContract]
void SendData(Stream clientProvidedWritableStream);
}
public class DataService : IStreamWriterService
{
public void GetData(Stream s)
{
do {
byte[] chunk = GetNextChunk();
s.Write(chunk,0, chunk.Length);
} while (chunk.Length > 0);
}
}
Run Code Online (Sandbox Code Playgroud)
这可能在WCF中,如果是这样,怎么样?绑定,界面等所需的配置设置是什么?什么是术语?
也许它会起作用?(我还没试过)
谢谢.
我相当肯定,有没有WCF绑定,这将让你的组合字面上写到客户端的数据流.这应该是合乎逻辑的,因为在表面之下的某个地方肯定会有一个NetworkStream,但是一旦你开始添加加密和所有有趣的东西,WCF将不得不知道如何包装这个流将它变成"真实的"消息,我不认为它.
但是,I-need-to-return-a-stream-but-component-X-want-to-write-to-one场景是一个常见的场景,我有一个全能解决方案,我用于这个场景,这是创建一个双向流并产生一个工作线程来写入它.在最简单和最安全的方式做到这一点(我的意思是,这涉及编写最少的代码,因此最有可能是越野车的方式)是使用匿名管道.
这是一个返回AnonymousPipeClientStream可以在WCF消息,MVC结果等中使用的方法的示例- 您想要反转方向的任何地方:
static Stream GetPipedStream(Action<Stream> writeAction)
{
AnonymousPipeServerStream pipeServer = new AnonymousPipeServerStream();
ThreadPool.QueueUserWorkItem(s =>
{
using (pipeServer)
{
writeAction(pipeServer);
pipeServer.WaitForPipeDrain();
}
});
return new AnonymousPipeClientStream(PipeDirection.In, pipeServer.ClientSafePipeHandle);
}
Run Code Online (Sandbox Code Playgroud)
一个示例用法是:
static Stream GetTestStream()
{
string data = "The quick brown fox jumps over the lazy dog.";
return GetPipedStream(s =>
{
StreamWriter writer = new StreamWriter(s);
writer.AutoFlush = true;
for (int i = 0; i < 50; i++)
{
Thread.Sleep(50);
writer.WriteLine(data);
}
});
}
Run Code Online (Sandbox Code Playgroud)
关于这种方法只有两点需要注意:
如果writeAction做任何事情来处理流,它将失败(这就是为什么测试方法实际上没有处理StreamWriter- 因为那会处置底层流);
如果writeAction实际上没有写入任何数据,它可能会失败,因为它WaitForPipeDrain会立即返回并创建竞争条件.(如果这是一个问题,你可以采取更多的防御措施来避免这种情况,但是对于罕见的边缘情况,它会使事情复杂化.)
希望这有助于您的具体情况.
| 归档时间: |
|
| 查看次数: |
10212 次 |
| 最近记录: |