gpt4 book ai didi

.net - WCF 和流式处理请求和响应

转载 作者:行者123 更新时间:2023-12-03 23:48:35 31 4
gpt4 key购买 nike

在 WCF 中,我不能将服务写入客户端接收的流,这是否正确?

WCF 支持流式处理请求、响应或两者。
我想支持数据生成器(在流式请求的情况下为客户端,或在流式响应的情况下为服务器)可以在流上写入的场景。这支持吗?

类比是来自 ASP.NET 请求的 Response.OutputStream。在 ASPNET 中,任何页面都可以在输出流上调用 Write,并且内容被客户端接收。我可以在 WCF 服务中执行类似的操作吗 - 在客户端接收的流上调用 Write?

让我用一个 WCF 插图来解释。 WCF 中流式处理的最简单示例是服务将 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)
}
}

客户端代码是这样的:
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);

(示例取自 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);
}
}

这在 WCF 中是否可行,如果可以,如何实现?绑定(bind)、接口(interface)等需要哪些配置设置?术语是什么?

也许它会起作用? (我没试过)

谢谢。

最佳答案

我相当确定没有任何 WCF 绑定(bind)组合可以让您从字面上写入客户端的流。应该有似乎是合乎逻辑的,因为在表面之下的某个地方肯定会有一个NetworkStream。 ,但是一旦你开始添加加密和所有有趣的东西,WCF 就必须知道如何包装这个流以将它变成“真正的”消息,我认为它不会这样做。

但是,I-need-to-return-a-stream-but-component-X-wants-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);
}

一个示例用法是:
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);
}
});
}

关于这种方法只有两个警告:
  • 如果 writeAction 将失败做任何事情来处理流(这就是为什么测试方法实际上没有处理 StreamWriter - 因为这会处理底层流);
  • 如果 writeAction 可能会失败实际上并没有写入任何数据,因为 WaitForPipeDrain将立即返回并创建竞争条件。 (如果这是一个问题,您可以编写更多防御性代码来避免这种情况,但对于罕见的边缘情况,它会使事情变得复杂。)

  • 希望这对您的具体情况有所帮助。

    关于.net - WCF 和流式处理请求和响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2726527/

    31 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com